diff --git a/lib/filters/filter.c b/lib/filters/filter.c index d09561433..a2ca7c6f5 100644 --- a/lib/filters/filter.c +++ b/lib/filters/filter.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,8 @@ typedef struct { int max_partitions; } device_info_t; +static int _md_major = -1; + static device_info_t device_info[] = { {"ide", 16}, /* IDE disk */ {"sd", 16}, /* SCSI disk */ @@ -96,6 +99,11 @@ struct dev_filter *lvm_type_filter_create(const char *proc) return f; } +int md_major(void) +{ + return _md_major; +} + void lvm_type_filter_destroy(struct dev_filter *f) { dbg_free(f->private); @@ -155,6 +163,10 @@ static int *scan_proc_dev(const char *proc) while (line[i] == ' ' && line[i] != '\0') i++; + /* Look for md device */ + if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2))) + _md_major = line_maj; + /* Go through the valid device names and if there is a match store max number of partitions */ for (j = 0; device_info[j].name != NULL; j++) { diff --git a/lib/filters/filter.h b/lib/filters/filter.h index e655599bf..7143acaf9 100644 --- a/lib/filters/filter.h +++ b/lib/filters/filter.h @@ -25,5 +25,7 @@ struct dev_filter *lvm_type_filter_create(); void lvm_type_filter_destroy(struct dev_filter *f); +int md_major(void); + #endif diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c index 575ccd66d..f22701317 100644 --- a/lib/format1/disk-rep.c +++ b/lib/format1/disk-rep.c @@ -9,10 +9,12 @@ #include "xlate.h" #include "log.h" #include "vgcache.h" +#include "filter.h" #include #include #include +#include #define fail do {stack; return 0;} while(0) #define xx16(v) disk->v = xlate16(disk->v) @@ -338,6 +340,29 @@ struct disk_list *read_disk(struct device *dev, struct pool *mem, return r; } +static void _add_pv_to_list(struct list *head, struct disk_list *data) +{ + struct list *pvdh; + struct pv_disk *pvd; + + list_iterate(pvdh, head) { + pvd = &list_item(pvdh, struct disk_list)->pvd; + if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid, + sizeof(pvd->pv_uuid))) { + if (MAJOR(data->dev->dev) != md_major()) { + log_debug("Ignoring duplicate PV %s on %s", + pvd->pv_uuid, dev_name(data->dev)); + return; + } + log_debug("Duplicate PV %s - using md %s", + pvd->pv_uuid, dev_name(data->dev)); + list_del(pvdh); + break; + } + } + list_add(head, &data->list); +} + /* * Build a list of pv_d's structures, allocated from mem. * We keep track of the first object allocated form the pool @@ -358,7 +383,7 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter, dev = list_item(pvdh2, struct pvdev_list)->dev; if (!(data = read_disk(dev, mem, vg_name))) break; - list_add(head, &data->list); + _add_pv_to_list(head, data); } /* Did we find the whole VG? */ @@ -380,7 +405,7 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter, /* Otherwise do a complete scan */ for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) { if ((data = read_disk(dev, mem, vg_name))) { - list_add(head, &data->list); + _add_pv_to_list(head, data); } } dev_iter_destroy(iter);