19
19
#include "display.h"
20
20
#include "toolcontext.h"
21
21
#include "lvmcache.h"
22
23
#include "lv_alloc.h"
23
24
#include "pv_alloc.h"
24
25
#include "segtype.h"
25
26
#include "text_import.h"
26
27
#include "defaults.h"
28
typedef int (*section_fn) (struct format_instance * fid, struct dm_pool * mem,
29
struct volume_group * vg, const struct config_node * pvn,
30
const struct config_node * vgn,
29
typedef int (*section_fn) (struct format_instance * fid,
30
struct volume_group * vg, const struct dm_config_node * pvn,
31
const struct dm_config_node * vgn,
31
32
struct dm_hash_table * pv_hash,
32
33
struct dm_hash_table * lv_hash,
33
34
unsigned *scan_done_once,
34
35
unsigned report_missing_devices);
36
37
#define _read_int32(root, path, result) \
37
get_config_uint32(root, path, (uint32_t *) result)
38
dm_config_get_uint32(root, path, (uint32_t *) result)
39
40
#define _read_uint32(root, path, result) \
40
get_config_uint32(root, path, result)
41
dm_config_get_uint32(root, path, result)
42
#define _read_int64(root, path, result) \
43
get_config_uint64(root, path, result)
43
#define _read_uint64(root, path, result) \
44
dm_config_get_uint64(root, path, result)
46
47
* Logs an attempt to read an invalid format file.
54
55
* Checks that the config file contains vg metadata, and that it
55
56
* we recognise the version number,
57
static int _vsn1_check_version(const struct config_tree *cft)
58
static int _vsn1_check_version(const struct dm_config_tree *cft)
59
const struct config_node *cn;
60
const struct config_value *cv;
60
const struct dm_config_node *cn;
61
const struct dm_config_value *cv;
63
// TODO if this is pvscan --cache, we want this check back.
63
68
* Check the contents field.
65
if (!(cn = find_config_node(cft->root, CONTENTS_FIELD))) {
70
if (!(cn = dm_config_find_node(cft->root, CONTENTS_FIELD))) {
66
71
_invalid_format("missing contents field");
71
if (!cv || cv->type != CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) {
76
if (!cv || cv->type != DM_CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) {
72
77
_invalid_format("unrecognised contents field");
77
82
* Check the version number.
79
if (!(cn = find_config_node(cft->root, FORMAT_VERSION_FIELD))) {
84
if (!(cn = dm_config_find_node(cft->root, FORMAT_VERSION_FIELD))) {
80
85
_invalid_format("missing version number");
85
if (!cv || cv->type != CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) {
90
if (!cv || cv->type != DM_CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) {
86
91
_invalid_format("unrecognised version number");
109
static int _read_id(struct id *id, const struct config_node *cn, const char *path)
114
static int _read_id(struct id *id, const struct dm_config_node *cn, const char *path)
111
const struct config_value *cv;
113
if (!(cn = find_config_node(cn, path))) {
118
if (!dm_config_get_str(cn, path, &uuid)) {
114
119
log_error("Couldn't find uuid.");
119
if (!cv || !cv->v.str) {
120
log_error("uuid must be a string.");
124
if (!id_read_format(id, cv->v.str)) {
123
if (!id_read_format(id, uuid)) {
125
124
log_error("Invalid uuid.");
132
static int _read_flag_config(const struct config_node *n, uint64_t *status, int type)
131
static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, int type)
134
const struct config_node *cn;
133
const struct dm_config_value *cv;
137
if (!(cn = find_config_node(n, "status"))) {
136
if (!dm_config_get_list(n, "status", &cv)) {
138
137
log_error("Could not find status flags.");
142
if (!(read_flags(status, type | STATUS_FLAG, cn->v))) {
141
if (!(read_flags(status, type | STATUS_FLAG, cv))) {
143
142
log_error("Could not read status flags.");
147
if ((cn = find_config_node(n, "flags"))) {
148
if (!(read_flags(status, type, cn->v))) {
146
if (dm_config_get_list(n, "flags", &cv)) {
147
if (!(read_flags(status, type, cv))) {
149
148
log_error("Could not read flags.");
157
static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
158
struct volume_group *vg, const struct config_node *pvn,
159
const struct config_node *vgn __attribute__((unused)),
156
static int _read_pv(struct format_instance *fid,
157
struct volume_group *vg, const struct dm_config_node *pvn,
158
const struct dm_config_node *vgn __attribute__((unused)),
160
159
struct dm_hash_table *pv_hash,
161
160
struct dm_hash_table *lv_hash __attribute__((unused)),
162
161
unsigned *scan_done_once,
163
162
unsigned report_missing_devices)
164
struct dm_pool *mem = vg->vgmem;
165
165
struct physical_volume *pv;
166
166
struct pv_list *pvl;
167
const struct config_node *cn;
167
const struct dm_config_value *cv;
170
170
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
196
196
* Convert the uuid into a device.
198
if (!(pv->dev = device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
198
if (!(pv->dev = lvmcache_device_from_pvid(fid->fmt->cmd, &pv->id, scan_done_once,
199
199
&pv->label_sector))) {
200
200
char buffer[64] __attribute__((aligned(8)));
220
/* TODO is the !lvmetad_active() too coarse here? */
221
if (!pv->dev && !lvmetad_active())
221
222
pv->status |= MISSING_PV;
223
224
/* Late addition */
224
_read_int64(pvn, "dev_size", &pv->size);
225
if (dm_config_has_node(pvn, "dev_size") &&
226
!_read_uint64(pvn, "dev_size", &pv->size)) {
227
log_error("Couldn't read dev size for physical volume.");
226
if (!_read_int64(pvn, "pe_start", &pv->pe_start)) {
231
if (!_read_uint64(pvn, "pe_start", &pv->pe_start)) {
227
232
log_error("Couldn't read extent size for physical volume.");
238
243
dm_list_init(&pv->segments);
240
245
/* Optional tags */
241
if ((cn = find_config_node(pvn, "tags")) &&
242
!(read_tags(mem, &pv->tags, cn->v))) {
246
if (dm_config_get_list(pvn, "tags", &cv) &&
247
!(read_tags(mem, &pv->tags, cv))) {
243
248
log_error("Couldn't read tags for physical volume %s in %s.",
244
249
pv_dev_name(pv), vg->name);
291
296
dm_list_add(&lv->segments, &seg->list);
294
static int _read_segment(struct dm_pool *mem, struct volume_group *vg,
295
struct logical_volume *lv, const struct config_node *sn,
299
static int _read_segment(struct logical_volume *lv, const struct dm_config_node *sn,
296
300
struct dm_hash_table *pv_hash)
302
struct dm_pool *mem = lv->vg->vgmem;
298
303
uint32_t area_count = 0u;
299
304
struct lv_segment *seg;
300
const struct config_node *cn, *sn_child = sn->child;
301
const struct config_value *cv;
305
const struct dm_config_node *sn_child = sn->child;
306
const struct dm_config_value *cv;
302
307
uint32_t start_extent, extent_count;
303
308
struct segment_type *segtype;
304
309
const char *segtype_str;
323
328
segtype_str = "striped";
325
if ((cn = find_config_node(sn_child, "type"))) {
327
if (!cv || !cv->v.str) {
328
log_error("Segment type must be a string.");
331
segtype_str = cv->v.str;
330
if (!dm_config_get_str(sn_child, "type", &segtype_str)) {
331
log_error("Segment type must be a string.");
334
if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str)))
335
if (!(segtype = get_segtype_from_string(lv->vg->cmd, segtype_str)))
337
338
if (segtype->ops->text_import_area_count &&
338
339
!segtype->ops->text_import_area_count(sn_child, &area_count))
341
if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent,
342
extent_count, 0, 0, NULL, area_count,
342
if (!(seg = alloc_lv_segment(segtype, lv, start_extent,
343
extent_count, 0, 0, NULL, NULL, area_count,
343
344
extent_count, 0, 0, 0, NULL))) {
344
345
log_error("Segment allocation failed");
352
353
/* Optional tags */
353
if ((cn = find_config_node(sn_child, "tags")) &&
354
!(read_tags(mem, &seg->tags, cn->v))) {
354
if (dm_config_get_list(sn_child, "tags", &cv) &&
355
!(read_tags(mem, &seg->tags, cv))) {
355
356
log_error("Couldn't read tags for a segment of %s/%s.",
357
lv->vg->name, lv->name);
380
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
381
const struct config_node *cn, struct dm_hash_table *pv_hash,
381
int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
382
const struct dm_config_value *cv, struct dm_hash_table *pv_hash,
385
const struct config_value *cv;
386
386
struct logical_volume *lv1;
387
387
struct physical_volume *pv;
388
const char *seg_name = config_parent_name(sn);
388
const char *seg_name = dm_config_parent_name(sn);
390
390
if (!seg->area_count) {
391
391
log_error("Zero areas not allowed for segment %s", seg_name);
395
for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) {
395
for (s = 0; cv && s < seg->area_count; s++, cv = cv->next) {
397
397
/* first we read the pv */
398
if (cv->type != CFG_STRING) {
398
if (cv->type != DM_CFG_STRING) {
399
399
log_error("Bad volume name in areas array for segment %s.", seg_name);
444
static int _read_segments(struct dm_pool *mem, struct volume_group *vg,
445
struct logical_volume *lv, const struct config_node *lvn,
444
static int _read_segments(struct logical_volume *lv, const struct dm_config_node *lvn,
446
445
struct dm_hash_table *pv_hash)
448
const struct config_node *sn;
447
const struct dm_config_node *sn;
449
448
int count = 0, seg_count;
451
450
for (sn = lvn; sn; sn = sn->sib) {
454
453
* All sub-sections are assumed to be segments.
457
if (!_read_segment(mem, vg, lv, sn, pv_hash))
456
if (!_read_segment(lv, sn, pv_hash))
496
495
static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
498
struct volume_group *vg, const struct config_node *lvn,
499
const struct config_node *vgn __attribute__((unused)),
496
struct volume_group *vg, const struct dm_config_node *lvn,
497
const struct dm_config_node *vgn __attribute__((unused)),
500
498
struct dm_hash_table *pv_hash __attribute__((unused)),
501
499
struct dm_hash_table *lv_hash,
502
500
unsigned *scan_done_once __attribute__((unused)),
503
501
unsigned report_missing_devices __attribute__((unused)))
503
struct dm_pool *mem = vg->vgmem;
505
504
struct logical_volume *lv;
506
const struct config_node *cn;
505
const char *lv_alloc;
506
const struct dm_config_value *cv;
507
const char *hostname;
508
uint64_t timestamp = 0;
508
510
if (!(lv = alloc_lv(mem)))
527
if (dm_config_has_node(lvn, "creation_time")) {
528
if (!_read_uint64(lvn, "creation_time", ×tamp)) {
529
log_error("Invalid creation_time for logical volume %s.",
533
if (!dm_config_get_str(lvn, "creation_host", &hostname)) {
534
log_error("Couldn't read creation_host for logical volume %s.",
538
} else if (dm_config_has_node(lvn, "creation_host")) {
539
log_error("Missing creation_time for logical volume %s.",
525
544
lv->alloc = ALLOC_INHERIT;
526
if ((cn = find_config_node(lvn, "allocation_policy"))) {
527
const struct config_value *cv = cn->v;
528
if (!cv || !cv->v.str) {
529
log_error("allocation_policy must be a string.");
533
lv->alloc = get_alloc_from_string(cv->v.str);
545
if (dm_config_get_str(lvn, "allocation_policy", &lv_alloc)) {
546
lv->alloc = get_alloc_from_string(lv_alloc);
534
547
if (lv->alloc == ALLOC_INVALID) {
535
log_warn("WARNING: Ignoring unrecognised allocation policy %s for LV %s", cv->v.str, lv->name);
548
log_warn("WARNING: Ignoring unrecognised allocation policy %s for LV %s", lv_alloc, lv->name);
536
549
lv->alloc = ALLOC_INHERIT;
556
569
/* Optional tags */
557
if ((cn = find_config_node(lvn, "tags")) &&
558
!(read_tags(mem, &lv->tags, cn->v))) {
570
if (dm_config_get_list(lvn, "tags", &cv) &&
571
!(read_tags(mem, &lv->tags, cv))) {
559
572
log_error("Couldn't read tags for logical volume %s/%s.",
560
573
vg->name, lv->name);
564
577
if (!dm_hash_insert(lv_hash, lv->name, lv))
567
return link_lv_to_vg(vg, lv);
580
if (!link_lv_to_vg(vg, lv))
583
if (timestamp && !lv_set_creation(lv, hostname, timestamp))
570
589
static int _read_lvsegs(struct format_instance *fid __attribute__((unused)),
572
struct volume_group *vg, const struct config_node *lvn,
573
const struct config_node *vgn __attribute__((unused)),
590
struct volume_group *vg, const struct dm_config_node *lvn,
591
const struct dm_config_node *vgn __attribute__((unused)),
574
592
struct dm_hash_table *pv_hash,
575
593
struct dm_hash_table *lv_hash,
576
594
unsigned *scan_done_once __attribute__((unused)),
598
616
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
600
if (!_read_segments(mem, vg, lv, lvn, pv_hash))
618
if (!_read_segments(lv, lvn, pv_hash))
603
621
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
623
641
static int _read_sections(struct format_instance *fid,
624
642
const char *section, section_fn fn,
626
struct volume_group *vg, const struct config_node *vgn,
643
struct volume_group *vg, const struct dm_config_node *vgn,
627
644
struct dm_hash_table *pv_hash,
628
645
struct dm_hash_table *lv_hash,
630
647
unsigned *scan_done_once)
632
const struct config_node *n;
649
const struct dm_config_node *n;
633
650
/* Only report missing devices when doing a scan */
634
651
unsigned report_missing_devices = scan_done_once ? !*scan_done_once : 1;
636
if (!(n = find_config_node(vgn, section))) {
653
if (!dm_config_get_section(vgn, section, &n)) {
638
655
log_error("Couldn't find section '%s'.", section);
645
662
for (n = n->child; n; n = n->sib) {
646
if (!fn(fid, mem, vg, n, vgn, pv_hash, lv_hash,
663
if (!fn(fid, vg, n, vgn, pv_hash, lv_hash,
647
664
scan_done_once, report_missing_devices))
654
671
static struct volume_group *_read_vg(struct format_instance *fid,
655
const struct config_tree *cft,
672
const struct dm_config_tree *cft,
656
673
unsigned use_cached_pvs)
658
const struct config_node *vgn, *cn;
675
const struct dm_config_node *vgn;
676
const struct dm_config_value *cv;
659
678
struct volume_group *vg;
660
679
struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL;
661
680
unsigned scan_done_once = use_cached_pvs;
675
694
if (!(vg->system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
698
* The pv hash memorises the pv section names -> pv
701
if (!(pv_hash = dm_hash_create(64))) {
702
log_error("Couldn't create pv hash table.");
707
* The lv hash memorises the lv section names -> lv
710
if (!(lv_hash = dm_hash_create(1024))) {
711
log_error("Couldn't create lv hash table.");
678
715
vgn = vgn->child;
680
if ((cn = find_config_node(vgn, "system_id")) && cn->v) {
682
log_error("system_id must be a string");
685
strncpy(vg->system_id, cn->v->v.str, NAME_LEN);
717
if (dm_config_get_str(vgn, "system_id", &str)) {
718
strncpy(vg->system_id, str, NAME_LEN);
688
721
if (!_read_id(&vg->id, vgn, "id")) {
728
if ((cn = find_config_node(vgn, "allocation_policy"))) {
729
const struct config_value *cv = cn->v;
730
if (!cv || !cv->v.str) {
731
log_error("allocation_policy must be a string.");
735
vg->alloc = get_alloc_from_string(cv->v.str);
761
if (dm_config_get_str(vgn, "allocation_policy", &str)) {
762
vg->alloc = get_alloc_from_string(str);
736
763
if (vg->alloc == ALLOC_INVALID) {
737
log_warn("WARNING: Ignoring unrecognised allocation policy %s for VG %s", cv->v.str, vg->name);
764
log_warn("WARNING: Ignoring unrecognised allocation policy %s for VG %s", str, vg->name);
738
765
vg->alloc = ALLOC_NORMAL;
743
770
vg->mda_copies = DEFAULT_VGMETADATACOPIES;
747
* The pv hash memorises the pv section names -> pv
750
if (!(pv_hash = dm_hash_create(64))) {
751
log_error("Couldn't create hash table.");
755
if (!_read_sections(fid, "physical_volumes", _read_pv, vg->vgmem, vg,
773
if (!_read_sections(fid, "physical_volumes", _read_pv, vg,
756
774
vgn, pv_hash, lv_hash, 0, &scan_done_once)) {
757
775
log_error("Couldn't find all physical volumes for volume "
758
776
"group %s.", vg->name);
762
780
/* Optional tags */
763
if ((cn = find_config_node(vgn, "tags")) &&
764
!(read_tags(vg->vgmem, &vg->tags, cn->v))) {
781
if (dm_config_get_list(vgn, "tags", &cv) &&
782
!(read_tags(vg->vgmem, &vg->tags, cv))) {
765
783
log_error("Couldn't read tags for volume group %s.", vg->name);
770
* The lv hash memorises the lv section names -> lv
773
if (!(lv_hash = dm_hash_create(1024))) {
774
log_error("Couldn't create hash table.");
778
if (!_read_sections(fid, "logical_volumes", _read_lvnames, vg->vgmem,
779
vg, vgn, pv_hash, lv_hash, 1, NULL)) {
787
if (!_read_sections(fid, "logical_volumes", _read_lvnames, vg,
788
vgn, pv_hash, lv_hash, 1, NULL)) {
780
789
log_error("Couldn't read all logical volume names for volume "
781
790
"group %s.", vg->name);
785
if (!_read_sections(fid, "logical_volumes", _read_lvsegs, vg->vgmem,
786
vg, vgn, pv_hash, lv_hash, 1, NULL)) {
794
if (!_read_sections(fid, "logical_volumes", _read_lvsegs, vg,
795
vgn, pv_hash, lv_hash, 1, NULL)) {
787
796
log_error("Couldn't read all logical volumes for "
788
797
"volume group %s.", vg->name);
821
830
static void _read_desc(struct dm_pool *mem,
822
const struct config_tree *cft, time_t *when, char **desc)
831
const struct dm_config_tree *cft, time_t *when, char **desc)
825
834
unsigned int u = 0u;
826
835
int old_suppress;
828
837
old_suppress = log_suppress(1);
829
d = find_config_str(cft->root, "description", "");
838
d = dm_config_find_str_allow_empty(cft->root, "description", "");
830
839
log_suppress(old_suppress);
831
840
*desc = dm_pool_strdup(mem, d);
833
(void) get_config_uint32(cft->root, "creation_time", &u);
842
(void) dm_config_get_uint32(cft->root, "creation_time", &u);
837
846
static const char *_read_vgname(const struct format_type *fmt,
838
const struct config_tree *cft, struct id *vgid,
847
const struct dm_config_tree *cft, struct id *vgid,
839
848
uint64_t *vgstatus, char **creation_host)
841
const struct config_node *vgn;
850
const struct dm_config_node *vgn;
842
851
struct dm_pool *mem = fmt->cmd->mem;
844
853
int old_suppress;
846
855
old_suppress = log_suppress(2);
847
856
*creation_host = dm_pool_strdup(mem,
848
find_config_str(cft->root,
857
dm_config_find_str_allow_empty(cft->root,
849
858
"creation_host", ""));
850
859
log_suppress(old_suppress);