From 6036e5e0f72220645c6e7f1ce49baa3185a4302c Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 15 Jan 2002 10:24:48 +0000 Subject: [PATCH] o split the uuid -> device map out from vgcache o roll vgcache back to agk's implementation, we'll revisit this as part of the cluster integration. o change the extra_info field in a label to be a void * --- include/.symlinks | 2 + lib/Makefile.in | 1 + lib/device/device.h | 5 + lib/format1/lvm1_label.c | 17 ++- lib/format1/lvm1_label.h | 9 ++ lib/label/label.c | 6 +- lib/label/label.h | 12 ++- lib/label/uuid-map.c | 70 +++++++++++++ lib/label/uuid-map.h | 26 +++++ lib/uuid/uuid.c | 4 +- lib/uuid/uuid.h | 2 +- lib/vgcache/vgcache.c | 216 +++++++++++++++++++++++---------------- lib/vgcache/vgcache.h | 46 ++++----- 13 files changed, 291 insertions(+), 125 deletions(-) create mode 100644 lib/label/uuid-map.c create mode 100644 lib/label/uuid-map.h diff --git a/include/.symlinks b/include/.symlinks index 9be795da2..53e5f6592 100644 --- a/include/.symlinks +++ b/include/.symlinks @@ -13,8 +13,10 @@ ../lib/filters/filter-regex.h ../lib/filters/filter.h ../lib/format1/format1.h +../lib/format1/lvm1_label.h ../lib/format_text/format-text.h ../lib/label/label.h +../lib/label/uuid-map.h ../lib/log/log.h ../lib/metadata/metadata.h ../lib/mm/dbg_malloc.h diff --git a/lib/Makefile.in b/lib/Makefile.in index 8f47e083f..d43dc3159 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -36,6 +36,7 @@ SOURCES=\ format_text/format-text.c \ format_text/import.c \ label/label.c \ + label/uuid-map.c \ log/log.c \ metadata/lv_manip.c \ metadata/merge.c \ diff --git a/lib/device/device.h b/lib/device/device.h index 1042d8c46..427a640fb 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -22,6 +22,11 @@ struct device { int fd; }; +struct device_list { + struct list list; + struct device *dev; +}; + /* * All io should use these routines. */ diff --git a/lib/format1/lvm1_label.c b/lib/format1/lvm1_label.c index 96c5c66ea..6ae1ebaa9 100644 --- a/lib/format1/lvm1_label.c +++ b/lib/format1/lvm1_label.c @@ -43,20 +43,25 @@ static int _remove(struct labeller *l, struct device *dev) static struct label *_to_label(struct disk_list *dl) { struct label *l; + struct lvm_label_info *info; if (!(l = dbg_malloc(sizeof(*l)))) { log_err("Couldn't allocate label."); return NULL; } + if (!(info = (struct lvm_label_info *) dbg_strdup(dl->pv.vg_name))) { + dbg_free(l); + return NULL; + } + memcpy(&l->id, &dl->pvd.pv_uuid, sizeof(l->id)); - strcpy(l->volume_type, "lvm1"); + strcpy(l->volume_type, "lvm"); l->version[0] = 1; l->version[0] = 0; l->version[0] = 0; + l->extra_info = info; - l->extra_len = 0; - l->extra_info = NULL; return l; } @@ -84,6 +89,12 @@ static int _read(struct labeller *l, return r; } +static int _destroy_label(struct labeller *l, struct label *label) +{ + dbg_free(label->extra_info); + dbg_free(label); +} + static void _destroy(struct labeller *l) { struct pool *mem = (struct pool *) l->private; diff --git a/lib/format1/lvm1_label.h b/lib/format1/lvm1_label.h index 210b46c2f..602f6a2cd 100644 --- a/lib/format1/lvm1_label.h +++ b/lib/format1/lvm1_label.h @@ -7,6 +7,15 @@ #ifndef _LVM_LVM1_LABEL_H #define _LVM_LVM1_LABEL_H +/* + * This is what the 'extra_info' field of the label will point to + * if the label type is lvm1. + */ +struct lvm_label_info { + char volume_group[0]; +}; + + struct labeller *lvm1_labeller_create(void); #endif diff --git a/lib/label/label.c b/lib/label/label.c index 6a02038c7..6289adb33 100644 --- a/lib/label/label.c +++ b/lib/label/label.c @@ -121,13 +121,17 @@ int label_remove(struct device *dev) int label_read(struct device *dev, struct label **result) { struct labeller *l; + int r; if (!(l = _find_labeller(dev))) { stack; return 0; } - return l->ops->read(l, dev, result); + if ((r = l->ops->read(l, dev, result))) + *result->labeller = l; + + return r; } int label_verify(struct device *dev) diff --git a/lib/label/label.h b/lib/label/label.h index cc2452380..911fd0b33 100644 --- a/lib/label/label.h +++ b/lib/label/label.h @@ -16,8 +16,9 @@ struct label { char volume_type[32]; uint32_t version[3]; - size_t extra_len; - char *extra_info; + void *extra_info; + + struct labeller *labeller; }; struct labeller; @@ -50,6 +51,11 @@ struct label_ops { */ int (*verify)(struct labeller *l, struct device *dev); + /* + * Destroy a previously read label. + */ + int (*destroy_label)(struct labeller *l, struct label *label); + /* * Destructor. */ @@ -72,7 +78,7 @@ struct labeller *label_get_handler(const char *name); int label_remove(struct device *dev); int label_read(struct device *dev, struct label **result); int label_verify(struct device *dev); -void label_free(struct label *l); +void label_destroy(struct label *lab); /* * We'll support two label types: the 'pretend the diff --git a/lib/label/uuid-map.c b/lib/label/uuid-map.c new file mode 100644 index 000000000..8280579ce --- /dev/null +++ b/lib/label/uuid-map.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#ifndef _LVM_UUID_MAP_H +#define _LVM_UUID_MAP_H + +#include "uuid-map.h" +#include "dev-cache.h" +#include "dbg_malloc.h" +#include "log.h" +#include "label.h" + +struct uuid_map { + struct dev_filter *filter; +}; + + +struct uuid_map *uuid_map_create(struct dev_filter *devices) +{ + struct uuid_map *um; + + if (!(um = dbg_malloc(sizeof(*um)))) { + log_err("Couldn't allocate uuid_map object."); + return NULL; + } + + um->filter = devices; + return um; +} + +void uuid_map_destroy(struct uuid_map *um) +{ + dbg_free(um); +} + +/* + * Simple, non-caching implementation to start with. + */ +struct device *uuid_map_lookup(struct uuid_map *um, struct id *id) +{ + struct dev_iter *iter; + struct device *dev; + struct label *lab; + + if (!(iter = dev_iter_create(um->filter))) { + stack; + return NULL; + } + + while ((dev = dev_iter_get(iter))) { + + if (!label_read(dev, &lab)) + continue; + + if (id_equal(id, &lab->id)) { + label_destroy(lab); + break; + } + + label_destroy(lab); + } + + dev_iter_destroy(iter); + return dev; +} + +#endif diff --git a/lib/label/uuid-map.h b/lib/label/uuid-map.h new file mode 100644 index 000000000..082905d78 --- /dev/null +++ b/lib/label/uuid-map.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#ifndef _LVM_UUID_MAP_H +#define _LVM_UUID_MAP_H + +#include "uuid.h" +#include "dev-cache.h" + +/* + * Holds a mapping from uuid -> device. + */ +struct uuid_map; + +struct uuid_map *uuid_map_create(struct dev_filter *devices); +void uuid_map_destroy(struct uuid_map *um); + +/* + * Find the device with a particular uuid. + */ +struct device *uuid_map_lookup(struct uuid_map *um, struct id *id); + +#endif diff --git a/lib/uuid/uuid.c b/lib/uuid/uuid.c index e6f09e8dd..4d1c9abc3 100644 --- a/lib/uuid/uuid.c +++ b/lib/uuid/uuid.c @@ -75,9 +75,9 @@ int id_valid(struct id *id) return 1; } -int id_cmp(struct id *lhs, struct id *rhs) +int id_equal(struct id *lhs, struct id *rhs) { - return memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid)); + return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid)); } #define GROUPS (ID_LEN / 4) diff --git a/lib/uuid/uuid.h b/lib/uuid/uuid.h index 8e4a3dedd..f979f3440 100644 --- a/lib/uuid/uuid.h +++ b/lib/uuid/uuid.h @@ -17,7 +17,7 @@ struct id { int id_create(struct id *id); int id_valid(struct id *id); -int id_cmp(struct id *lhs, struct id *rhs); +int id_equal(struct id *lhs, struct id *rhs); /* * Fills 'buffer' with a more human readable form diff --git a/lib/vgcache/vgcache.c b/lib/vgcache/vgcache.c index db682aac6..2ad924e3e 100644 --- a/lib/vgcache/vgcache.c +++ b/lib/vgcache/vgcache.c @@ -1,139 +1,181 @@ /* - * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2001 Sistina Software (UK) Limited. * * This file is released under the LGPL. + * */ #include - #include "vgcache.h" -#include "label.h" +#include "hash.h" #include "dbg_malloc.h" #include "log.h" -#include "lvm1_label.h" +static struct hash_table *_vghash; +static struct hash_table *_pvhash; -/* - * Non-caching implementation. - * FIXME: write caching version, when thought about it a bit more. - */ -struct vg_cache { - struct dev_filter *filter; -}; +const char *all_devices = "\0"; -struct vg_cache *vg_cache_create(struct dev_filter *devices) +int vgcache_init() { - struct vg_cache *vgc; + if (!(_vghash = hash_create(128))) + return 0; + + if (!(_pvhash = hash_create(128))) + return 0; - if (!(vgc = dbg_malloc(sizeof(*vgc)))) { - log_err("Couldn't allocate vg_cache object."); + return 1; +} + +/* A vg_name of NULL returns all_devices */ +struct list *vgcache_find(const char *vg_name) +{ + struct vgname_entry *vgn; + + if (!_vghash) return NULL; - } - vgc->filter = devices; + if (!vg_name) + vg_name = all_devices; - return vgc; + if (!(vgn = hash_lookup(_vghash, vg_name))) + return NULL; + + return &vgn->pvdevs; } -void vg_cache_destroy(struct vg_cache *vgc) +void vgcache_del_orphan(struct device *dev) { - dbg_free(vgc); + struct pvdev_list *pvdev; + + if (_pvhash && ((pvdev = hash_lookup(_pvhash, dev_name(dev))))) { + list_del(&pvdev->list); + hash_remove(_pvhash, dev_name(pvdev->dev)); + dbg_free(pvdev); + } } -struct device *vg_cache_find_uuid(struct vg_cache *vgc, struct id *id) +int vgcache_add_entry(const char *vg_name, struct device *dev) { - struct dev_iter *iter; - struct device *dev; - struct label *lab; + const char *pv_name; + struct vgname_entry *vgn; + struct pvdev_list *pvdev; + struct list *pvdh, *pvdevs; + + if (!(pvdevs = vgcache_find(vg_name))) { + if (!(vgn = dbg_malloc(sizeof(struct vgname_entry)))) { + log_error("struct vgname_entry allocation failed"); + return 0; + } - if (!(iter = dev_iter_create(vgc->filter))) { - stack; - return NULL; - } + pvdevs = &vgn->pvdevs; + list_init(pvdevs); - while ((dev = dev_iter_get(iter))) { + if (!(vgn->vgname = dbg_strdup(vg_name))) { + log_error("vgcache_add: strdup vg_name failed"); + return 0; + } - if (label_read(dev, &lab)) - continue; + if (!hash_insert(_vghash, vg_name, vgn)) { + log_error("vgcache_add: VG hash insertion failed"); + return 0; + } + } - if (!strcmp(lab->volume_type, "lvm") && id_equal(id, &lab->id)) - break; + list_iterate(pvdh, pvdevs) { + pvdev = list_item(pvdh, struct pvdev_list); + if (dev == pvdev->dev) + return 1; + } - label_destroy(lab); + /* Remove PV from any existing VG unless an all_devices request */ + pvdev = NULL; + pv_name = dev_name(dev); + if (*vg_name && _pvhash && ((pvdev = hash_lookup(_pvhash, pv_name)))) { + list_del(&pvdev->list); + hash_remove(_pvhash, dev_name(pvdev->dev)); } - dev_iter_destroy(iter); - return dev; -} + /* Allocate new pvdev_list if there isn't an existing one to reuse */ + if (!pvdev && !(pvdev = dbg_malloc(sizeof(struct pvdev_list)))) { + log_error("struct pvdev_list allocation failed"); + return 0; + } -static void _find_pvs_in_vg(struct vg_cache *vgc, struct pool *mem, - const char *vg, struct dev_iter *iter, - struct list *results) -{ - struct device *dev; - struct label *lab; - struct device_list *dev_list; - struct lvm_label_info *info; + pvdev->dev = dev; + list_add(pvdevs, &pvdev->list); - while ((dev = dev_iter_get(iter))) { + if (*vg_name && _pvhash && !hash_insert(_pvhash, pv_name, pvdev)) { + log_error("vgcache_add: PV hash insertion for %s " + "failed", pv_name); + return 0; + } - if (!label_read(dev, &lab)) - continue; + return 1; +} - if (strcmp(lab->volume_type, "lvm")) - continue; +/* vg_name of "\0" is an orphan PV; NULL means only add to all_devices */ +int vgcache_add(const char *vg_name, struct device *dev) +{ + if (!_vghash && !vgcache_init()) + return 0; - info = (struct lvm_label_info *) lab->extra_info; + /* If orphan PV remove it */ + if (vg_name && !*vg_name) + vgcache_del_orphan(dev); - if (!vg || strcmp(info->volume_group, vg)) { + /* Add PV if vg_name supplied */ + if (vg_name && *vg_name && !vgcache_add_entry(vg_name, dev)) + return 0; - /* add dev to the result list */ - if (!(dev_list = pool_alloc(mem, sizeof(*dev_list)))) { - stack; - label_destroy(lab); - return; - } + /* Always add to all_devices */ + return vgcache_add_entry(all_devices, dev); +} - dev_list->dev = dev; - list_add(results, &dev_list->list); +void vgcache_destroy_entry(struct vgname_entry *vgn) +{ + struct list *pvdh; + struct pvdev_list *pvdev; + + if (vgn) { + pvdh = vgn->pvdevs.n; + while (pvdh != &vgn->pvdevs) { + pvdev = list_item(pvdh, struct pvdev_list); + pvdh = pvdh->n; + dbg_free(pvdev); } - - label_destroy(lab); + dbg_free(vgn->vgname); } + dbg_free(vgn); } -struct list *vg_cache_find_vg(struct vg_cache *vgc, struct pool *mem, - const char *vg) +void vgcache_del(const char *vg_name) { - struct dev_iter *iter; - struct list *r; + struct vgname_entry *vgn; - if (!(r = pool_alloc(mem, sizeof(r)))) { - stack; - return NULL; - } - list_init(r); + if (!_vghash) + return; - if (!(iter = dev_iter_create(vgc->filter))) { - stack; - pool_free(mem, r); - return NULL; - } + if (!vg_name) + vg_name = all_devices; - _find_pvs_in_vg(vgc, mem, vg, iter, r); + if (!(vgn = hash_lookup(_vghash, vg_name))) + return; - dev_iter_destroy(iter); - return r; + hash_remove(_vghash, vg_name); + vgcache_destroy_entry(vgn); } -int vg_cache_update_vg(struct volume_group *vg) +void vgcache_destroy() { - /* no-ops in a non caching version */ - return 1; -} + if (_vghash) { + hash_iterate(_vghash, (iterate_fn)vgcache_destroy_entry); + hash_destroy(_vghash); + _vghash = NULL; + } -int vg_cache_update_device(struct device *dev) -{ - /* no-ops in a non caching version */ - return 1; + if (_pvhash) { + hash_destroy(_pvhash); + _pvhash = NULL; + } } diff --git a/lib/vgcache/vgcache.h b/lib/vgcache/vgcache.h index 364c75251..caa7815e8 100644 --- a/lib/vgcache/vgcache.h +++ b/lib/vgcache/vgcache.h @@ -8,39 +8,29 @@ #ifndef _LVM_VGCACHE_H #define _LVM_VGCACHE_H -#include "vgcache.h" -#include "list.h" -#include "uuid.h" -#include "pool.h" +#include +#include #include "dev-cache.h" -#include "metadata.h" +#include "list.h" +struct vgname_entry { + struct list pvdevs; + char *vgname; +}; -/* - * Maintains a register of LVM specific information about - * devices. Makes use of the label code. - */ -struct vg_cache; +struct pvdev_list { + struct list list; + struct device *dev; +}; -struct vg_cache *vg_cache_create(struct dev_filter *devices); -void vg_cache_destroy(struct vg_cache *vgc); +int vgcache_init(); +void vgcache_destroy(); -/* - * Find the device with a particular uuid. - */ -struct device *vg_cache_find_uuid(struct vg_cache *vgc, struct id *id); +/* Return list of PVs in named VG */ +struct list *vgcache_find(const char *vg_name); -/* - * Find all devices in a particular volume group. - */ -struct list *vg_cache_find_vg(struct vg_cache *vgc, struct pool *mem, - const char *vg); - -/* - * Tell the cache about any changes occuring on disk. - * FIXME: it would be nice to do without these. - */ -int vg_cache_update_vg(struct volume_group *vg); -int vg_cache_update_device(struct device *dev); +/* Add/delete a device */ +int vgcache_add(const char *vg_name, struct device *dev); +void vgcache_del(const char *vg_name); #endif -- 2.43.5