From 74b27447c1070c55d922620ba2b1f6bc7257766c Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Mon, 18 Nov 2002 13:53:58 +0000 Subject: [PATCH] A new cache. --- lib/cache/cache.c | 491 ++++++++++++++++++++++++++++++++++++++++++ lib/cache/cache.h | 73 +++++++ lib/vgcache/vgcache.c | 295 ------------------------- lib/vgcache/vgcache.h | 46 ---- 4 files changed, 564 insertions(+), 341 deletions(-) create mode 100644 lib/cache/cache.c create mode 100644 lib/cache/cache.h delete mode 100644 lib/vgcache/vgcache.c delete mode 100644 lib/vgcache/vgcache.h diff --git a/lib/cache/cache.c b/lib/cache/cache.c new file mode 100644 index 000000000..63587aa91 --- /dev/null +++ b/lib/cache/cache.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + * + */ + +#include "lib.h" +#include "cache.h" +#include "hash.h" +#include "toolcontext.h" +#include "dev-cache.h" +#include "metadata.h" + +static struct hash_table *_pvid_hash = NULL; +static struct hash_table *_vgid_hash = NULL; +static struct hash_table *_vgname_hash = NULL; +static struct list _vginfos; +int _has_scanned = 0; + +int cache_init() +{ + list_init(&_vginfos); + + if (!(_vgname_hash = hash_create(128))) + return 0; + + if (!(_vgid_hash = hash_create(128))) + return 0; + + if (!(_pvid_hash = hash_create(128))) + return 0; + + return 1; +} + +struct cache_vginfo *vginfo_from_vgname(const char *vgname) +{ + struct cache_vginfo *vginfo; + + if (!_vgname_hash) + return NULL; + + if (!(vginfo = hash_lookup(_vgname_hash, vgname))) + return NULL; + + return vginfo; +} + +struct format_type *fmt_from_vgname(const char *vgname) +{ + struct cache_vginfo *vginfo; + + if (!(vginfo = vginfo_from_vgname(vgname))) + return NULL; + + return vginfo->fmt; +} + +struct cache_vginfo *vginfo_from_vgid(const char *vgid) +{ + struct cache_vginfo *vginfo; + + if (!_vgid_hash || !vgid) + return NULL; + + if (!(vginfo = hash_lookup_fixed(_vgid_hash, vgid, ID_LEN))) + return NULL; + + return vginfo; +} + +struct cache_info *info_from_pvid(const char *pvid) +{ + struct cache_info *info; + + if (!_pvid_hash || !pvid) + return NULL; + + if (!(info = hash_lookup_fixed(_pvid_hash, pvid, ID_LEN))) + return NULL; + + return info; +} + +static void _rescan_entry(struct cache_info *info) +{ + struct label *label; + + if (info->status & CACHE_INVALID) + label_read(info->dev, &label); +} + +static int _scan_invalid(struct cmd_context *cmd) +{ + hash_iter(_pvid_hash, (iterate_fn) _rescan_entry); + + return 1; +} + +int cache_label_scan(struct cmd_context *cmd, int full_scan) +{ + struct label *label; + struct dev_iter *iter; + struct device *dev; + struct list *fmth; + struct format_type *fmt; + + static int _scanning_in_progress = 0; + int r = 0; + + /* Avoid recursion when a PVID can't be found! */ + if (_scanning_in_progress) + return 0; + + _scanning_in_progress = 1; + + if (!_vgname_hash && !cache_init()) { + log_error("Internal cache initialisation failed"); + goto out; + } + + if (_has_scanned && !full_scan) { + r = _scan_invalid(cmd); + goto out; + } + + if (!(iter = dev_iter_create(cmd->filter))) { + log_error("dev_iter creation failed"); + goto out; + } + + while ((dev = dev_iter_get(iter))) + label_read(dev, &label); + + dev_iter_destroy(iter); + + _has_scanned = 1; + + /* Perform any format-specific scanning e.g. text files */ + list_iterate(fmth, &cmd->formats) { + fmt = list_item(fmth, struct format_type); + if (fmt->ops->scan && !fmt->ops->scan(fmt)) + goto out; + } + + r = 1; + + out: + _scanning_in_progress = 0; + + return r; +} + +struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan) +{ + struct list *vgih, *vgnames; + struct str_list *sl; + + cache_label_scan(cmd, full_scan); + + if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) { + log_error("vgnames list allocation failed"); + return NULL; + } + + list_init(vgnames); + + list_iterate(vgih, &_vginfos) { + if (!(sl = pool_alloc(cmd->mem, sizeof(*sl)))) { + log_error("strlist allocation failed"); + return NULL; + } + if (!(sl->str = pool_strdup(cmd->mem, + list_item(vgih, + struct cache_vginfo)-> + vgname))) { + log_error("vgname allocation failed"); + return NULL; + } + list_add(vgnames, &sl->list); + } + + return vgnames; +} + +struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid) +{ + struct label *label; + struct cache_info *info; + + /* Already cached ? */ + if ((info = info_from_pvid((char *) pvid))) { + if (label_read(info->dev, &label)) { + info = (struct cache_info *) label->info; + if (id_equal(pvid, (struct id *) &info->dev->pvid)) + return info->dev; + } + } + + cache_label_scan(cmd, 0); + + /* Try again */ + if ((info = info_from_pvid((char *) pvid))) { + if (label_read(info->dev, &label)) { + info = (struct cache_info *) label->info; + if (id_equal(pvid, (struct id *) &info->dev->pvid)) + return info->dev; + } + } + + cache_label_scan(cmd, 1); + + /* Try again */ + if ((info = info_from_pvid((char *) pvid))) { + if (label_read(info->dev, &label)) { + info = (struct cache_info *) label->info; + if (id_equal(pvid, (struct id *) &info->dev->pvid)) + return info->dev; + } + } + + return NULL; +} + +void _drop_vginfo(struct cache_info *info) +{ + if (!list_empty(&info->list)) { + list_del(&info->list); + list_init(&info->list); + } + + if (info->vginfo && list_empty(&info->vginfo->infos)) { + hash_remove(_vgname_hash, info->vginfo->vgname); + if (info->vginfo->vgname) + dbg_free(info->vginfo->vgname); + if (*info->vginfo->vgid) + hash_remove(_vgid_hash, info->vginfo->vgid); + list_del(&info->vginfo->list); + dbg_free(info->vginfo); + } + + info->vginfo = NULL; +} + +/* Unused +void cache_del(struct cache_info *info) +{ + if (info->dev->pvid[0] && _pvid_hash) + hash_remove(_pvid_hash, info->dev->pvid); + + _drop_vginfo(info); + + info->label->labeller->ops->destroy_label(info->label->labeller, + info->label); + dbg_free(info); + + return; +} */ + +static int _cache_update_pvid(struct cache_info *info, const char *pvid) +{ + if (!strcmp(info->dev->pvid, pvid)) + return 1; + if (*info->dev->pvid) { + hash_remove(_pvid_hash, info->dev->pvid); + } + strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid)); + if (!hash_insert(_pvid_hash, pvid, info)) { + log_error("_cache_update: pvid insertion failed: %s", pvid); + return 0; + } + + return 1; +} + +static int _cache_update_vgid(struct cache_info *info, const char *vgid) +{ + if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid, + sizeof(info->vginfo->vgid))) + return 1; + + if (info->vginfo && *info->vginfo->vgid) + hash_remove(_vgid_hash, info->vginfo->vgid); + if (!vgid) + return 1; + + strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid)); + info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0'; + if (!hash_insert(_vgid_hash, vgid, info->vginfo)) { + log_error("_cache_update: vgid hash insertion failed: %s", + vgid); + return 0; + } + + return 1; +} + +int cache_update_vgname(struct cache_info *info, const char *vgname) +{ + struct cache_vginfo *vginfo; + + /* If vgname is NULL and we don't already have a vgname, + * assume ORPHAN - we want every entry to have a vginfo + * attached for scanning reasons. + */ + if (!vgname && !info->vginfo) + vgname = ORPHAN; + + if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname))) + return 1; + + /* Remove existing vginfo entry */ + _drop_vginfo(info); + + /* Get existing vginfo or create new one */ + if (!(vginfo = vginfo_from_vgname(vgname))) { + if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) { + log_error("cache_update_vgname: list alloc failed"); + return 0; + } + memset(vginfo, 0, sizeof(*vginfo)); + if (!(vginfo->vgname = dbg_strdup(vgname))) { + dbg_free(vginfo); + log_error("cache vgname alloc failed for %s", vgname); + return 0; + } + list_init(&vginfo->infos); + if (!hash_insert(_vgname_hash, vginfo->vgname, vginfo)) { + log_error("cache_update: vg hash insertion failed: %s", + vginfo->vgname); + dbg_free(vginfo->vgname); + dbg_free(vginfo); + return 0; + } + /* Ensure orphans appear last on list_iterate */ + if (!*vgname) + list_add(&_vginfos, &vginfo->list); + else + list_add_h(&_vginfos, &vginfo->list); + } + + info->vginfo = vginfo; + list_add(&vginfo->infos, &info->list); + + /* FIXME Check consistency of list! */ + vginfo->fmt = info->fmt; + + return 1; +} + +int cache_update_vg(struct volume_group *vg) +{ + struct list *pvh; + struct physical_volume *pv; + struct cache_info *info; + char pvid_s[ID_LEN + 1]; + int vgid_updated = 0; + + pvid_s[sizeof(pvid_s) - 1] = '\0'; + + list_iterate(pvh, &vg->pvs) { + pv = list_item(pvh, struct pv_list)->pv; + strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1); + /* FIXME Could pv->dev->pvid ever be different? */ + if ((info = info_from_pvid(pvid_s))) { + cache_update_vgname(info, vg->name); + if (!vgid_updated) { + _cache_update_vgid(info, (char *) &vg->id); + vgid_updated = 1; + } + } + } + + return 1; +} + +struct cache_info *cache_add(struct labeller *labeller, const char *pvid, + struct device *dev, + const char *vgname, const char *vgid) +{ + struct label *label; + struct cache_info *existing, *info; + char pvid_s[ID_LEN + 1]; + + if (!_vgname_hash && !cache_init()) { + log_error("Internal cache initialisation failed"); + return NULL; + } + + strncpy(pvid_s, pvid, sizeof(pvid_s)); + pvid_s[sizeof(pvid_s) - 1] = '\0'; + + if (!(existing = info_from_pvid(pvid_s)) && + !(existing = info_from_pvid(dev->pvid))) { + if (!(label = label_create(labeller))) { + stack; + return NULL; + } + if (!(info = dbg_malloc(sizeof(*info)))) { + log_error("cache_info allocation failed"); + label_destroy(label); + return NULL; + } + memset(info, 0, sizeof(*info)); + + label->info = info; + info->label = label; + list_init(&info->list); + info->dev = dev; + } else { + info = existing; + /* Has labeller changed? */ + if (info->label->labeller != labeller) { + label_destroy(info->label); + if (!(info->label = label_create(labeller))) { + /* FIXME leaves info without label! */ + stack; + return NULL; + } + info->label->info = info; + } + label = info->label; + } + + info->fmt = (struct format_type *) labeller->private; + info->status |= CACHE_INVALID; + + if (!_cache_update_pvid(info, pvid_s)) { + if (!existing) { + dbg_free(info); + label_destroy(label); + } + return NULL; + } + + if (!cache_update_vgname(info, vgname)) { + if (!existing) { + hash_remove(_pvid_hash, pvid_s); + strcpy(info->dev->pvid, ""); + dbg_free(info); + label_destroy(label); + } + return NULL; + } + + if (!_cache_update_vgid(info, vgid)) + /* Non-critical */ + stack; + + return info; +} + +static void _cache_destroy_entry(struct cache_info *info) +{ + if (!list_empty(&info->list)) + list_del(&info->list); + strcpy(info->dev->pvid, ""); + label_destroy(info->label); + dbg_free(info); +} + +static void _cache_destroy_vgnamelist(struct cache_vginfo *vginfo) +{ + if (vginfo->vgname) + dbg_free(vginfo->vgname); + dbg_free(vginfo); +} + +void cache_destroy() +{ + _has_scanned = 0; + + if (_vgid_hash) { + hash_destroy(_vgid_hash); + _vgid_hash = NULL; + } + + if (_pvid_hash) { + hash_iter(_pvid_hash, (iterate_fn) _cache_destroy_entry); + hash_destroy(_pvid_hash); + _pvid_hash = NULL; + } + + if (_vgname_hash) { + hash_iter(_vgname_hash, (iterate_fn) _cache_destroy_vgnamelist); + hash_destroy(_vgname_hash); + _vgname_hash = NULL; + } + list_init(&_vginfos); +} diff --git a/lib/cache/cache.h b/lib/cache/cache.h new file mode 100644 index 000000000..101e1f005 --- /dev/null +++ b/lib/cache/cache.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + * + */ + +#ifndef _LVM_CACHE_H +#define _LVM_CACHE_H + +#include "dev-cache.h" +#include "list.h" +#include "uuid.h" +#include "label.h" +#include "metadata.h" + +#include + +#define ORPHAN "" + +#define CACHE_INVALID 0x00000001 + +/* LVM specific per-volume info */ +/* Eventual replacement for struct physical_volume perhaps? */ + +struct cache_vginfo { + struct list list; /* Join these vginfos together */ + struct list infos; /* List head for cache_infos */ + char *vgname; /* "" == orphan */ + char vgid[ID_LEN + 1]; + struct format_type *fmt; +}; + +struct cache_info { + struct list list; /* Join VG members together */ + struct list mdas; /* list head for metadata areas */ + struct list das; /* list head for data areas */ + struct cache_vginfo *vginfo; /* NULL == unknown */ + struct label *label; + struct format_type *fmt; + struct device *dev; + uint64_t device_size; /* Bytes */ + uint32_t status; +}; + +int cache_init(); +void cache_destroy(); + +/* Set full_scan to 1 to reread every filtered device label */ +int cache_label_scan(struct cmd_context *cmd, int full_scan); + +/* Add/delete a device */ +struct cache_info *cache_add(struct labeller *labeller, const char *pvid, + struct device *dev, + const char *vgname, const char *vgid); +void cache_del(struct cache_info *info); + +/* Update things */ +int cache_update_vgname(struct cache_info *info, const char *vgname); +int cache_update_vg(struct volume_group *vg); + +/* Queries */ +struct format_type *fmt_from_vgname(const char *vgname); +struct cache_vginfo *vginfo_from_vgname(const char *vgname); +struct cache_vginfo *vginfo_from_vgid(const char *vgid); +struct cache_info *info_from_pvid(const char *pvid); +struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid); + +/* Returns list of struct str_lists containing pool-allocated copy of vgnames */ +/* Set full_scan to 1 to reread every filtered device label */ +struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan); + +#endif diff --git a/lib/vgcache/vgcache.c b/lib/vgcache/vgcache.c deleted file mode 100644 index a6a92af2c..000000000 --- a/lib/vgcache/vgcache.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software (UK) Limited. - * - * This file is released under the LGPL. - * - */ - -#include -#include "vgcache.h" -#include "hash.h" -#include "dbg_malloc.h" -#include "log.h" -#include "uuid.h" -#include "toolcontext.h" - -static struct hash_table *_vghash; -static struct hash_table *_vgidhash; -static struct hash_table *_pvhash; - -const char *all_devices = "\0"; - -int vgcache_init() -{ - if (!(_vghash = hash_create(128))) - return 0; - - if (!(_vgidhash = hash_create(128))) - return 0; - - if (!(_pvhash = hash_create(128))) - return 0; - - 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; - - if (!vg_name) - vg_name = all_devices; - - if (!(vgn = hash_lookup(_vghash, vg_name))) - return NULL; - - return &vgn->pvdevs; -} - -struct format_type *vgcache_find_format(const char *vg_name) -{ - struct vgname_entry *vgn; - - if (!_vghash) - return NULL; - - if (!vg_name) - vg_name = all_devices; - - if (!(vgn = hash_lookup(_vghash, vg_name))) - return NULL; - - return vgn->fmt; -} - -struct list *vgcache_find_by_vgid(const char *vgid) -{ - struct vgname_entry *vgn; - char vgid_s[ID_LEN + 1]; - - if (!_vgidhash || !vgid) - return NULL; - - memcpy(vgid_s, vgid, ID_LEN); - vgid_s[ID_LEN] = '\0'; - - if (!(vgn = hash_lookup(_vgidhash, vgid_s))) - return NULL; - - return &vgn->pvdevs; -} - -void vgcache_del_orphan(struct device *dev) -{ - 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); - } -} - -int vgcache_add_entry(const char *vg_name, const char *vgid, struct device *dev, - struct format_type *fmt) -{ - 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; - } - memset(vgn, 0, sizeof(struct vgname_entry)); - - vgn->fmt = fmt; - pvdevs = &vgn->pvdevs; - list_init(pvdevs); - - if (!(vgn->vgname = dbg_strdup(vg_name))) { - log_error("vgcache_add: strdup vg_name failed"); - return 0; - } - - if (!hash_insert(_vghash, vg_name, vgn)) { - log_error("vgcache_add: VG hash insertion failed"); - return 0; - } - } else if (!(vgn = hash_lookup(_vghash, vg_name))) { - log_error("vgcache_add: VG name entry %s not found", vg_name); - return 0; - } - - if (vgid && strncmp(vgid, vgn->vgid, ID_LEN)) { - hash_remove(_vgidhash, vgn->vgid); - - memcpy(vgn->vgid, vgid, ID_LEN); - vgn->vgid[ID_LEN] = '\0'; - - if (!hash_insert(_vgidhash, vgn->vgid, vgn)) { - log_error("vgcache_add: vgid hash insertion " "failed"); - return 0; - } - } - - if (!dev) - return 1; - - list_iterate(pvdh, pvdevs) { - pvdev = list_item(pvdh, struct pvdev_list); - if (dev == pvdev->dev) - return 1; - } - - /* 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)); - } - - /* 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; - } - - pvdev->dev = dev; - list_add(pvdevs, &pvdev->list); - - if (*vg_name && _pvhash && !hash_insert(_pvhash, pv_name, pvdev)) { - log_error("vgcache_add: PV hash insertion for %s " - "failed", pv_name); - return 0; - } - - return 1; -} - -/* vg_name of "\0" is an orphan PV; NULL means only add to all_devices */ -int vgcache_add(const char *vg_name, const char *vgid, struct device *dev, - struct format_type *fmt) -{ - if (!_vghash && !vgcache_init()) - return 0; - - /* If orphan PV remove it */ - if (dev && vg_name && !*vg_name) - vgcache_del_orphan(dev); - - /* Add PV if vg_name supplied */ - if (vg_name && *vg_name && !vgcache_add_entry(vg_name, vgid, dev, fmt)) - return 0; - - /* Add to all_devices */ - if (dev) - return vgcache_add_entry(all_devices, NULL, dev, fmt); - - return 1; -} - -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; - if (_pvhash) - hash_remove(_pvhash, dev_name(pvdev->dev)); - dbg_free(pvdev); - } - dbg_free(vgn->vgname); - if (_vgidhash && vgn->vgid[0]) - hash_remove(_vgidhash, vgn->vgid); - } - dbg_free(vgn); -} - -void vgcache_del(const char *vg_name) -{ - struct vgname_entry *vgn; - - if (!_vghash) - return; - - if (!vg_name) - vg_name = all_devices; - - if (!(vgn = hash_lookup(_vghash, vg_name))) - return; - - hash_remove(_vghash, vg_name); - if (vgn->vgid[0]) - hash_remove(_vgidhash, vgn->vgid); - - vgcache_destroy_entry(vgn); -} - -void vgcache_del_by_vgid(const char *vgid) -{ - struct vgname_entry *vgn; - char vgid_s[ID_LEN + 1]; - - if (!_vgidhash || !vgid) - return; - - memcpy(vgid_s, vgid, ID_LEN); - vgid_s[ID_LEN] = '\0'; - - if (!(vgn = hash_lookup(_vghash, vgid_s))) - return; - - hash_remove(_vgidhash, vgn->vgid); - if (vgn->vgname[0]) - hash_remove(_vghash, vgn->vgname); - - vgcache_destroy_entry(vgn); -} - -void vgcache_destroy() -{ - if (_vghash) { - hash_iter(_vghash, (iterate_fn) vgcache_destroy_entry); - hash_destroy(_vghash); - _vghash = NULL; - } - - if (_vgidhash) { - hash_destroy(_vgidhash); - _vgidhash = NULL; - } - - if (_pvhash) { - hash_destroy(_pvhash); - _pvhash = NULL; - } -} - -char *vgname_from_vgid(struct cmd_context *cmd, struct id *vgid) -{ - struct vgname_entry *vgn; - char vgid_s[ID_LEN + 1]; - - if (!_vgidhash || !vgid) - return NULL; - - memcpy(vgid_s, vgid->uuid, ID_LEN); - vgid_s[ID_LEN] = '\0'; - - if (!(vgn = hash_lookup(_vgidhash, vgid_s))) - return NULL; - - return pool_strdup(cmd->mem, vgn->vgname); -} diff --git a/lib/vgcache/vgcache.h b/lib/vgcache/vgcache.h deleted file mode 100644 index 47fd2ede2..000000000 --- a/lib/vgcache/vgcache.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software (UK) Limited. - * - * This file is released under the LGPL. - * - */ - -#ifndef _LVM_VGCACHE_H -#define _LVM_VGCACHE_H - -#include -#include -#include "dev-cache.h" -#include "list.h" -#include "uuid.h" -#include "toolcontext.h" - -struct vgname_entry { - struct list pvdevs; - char *vgname; - char vgid[ID_LEN + 1]; - struct format_type *fmt; -}; - -struct pvdev_list { - struct list list; - struct device *dev; -}; - -int vgcache_init(); -void vgcache_destroy(); - -/* Return list of PVs in named VG */ -struct list *vgcache_find(const char *vg_name); -struct format_type *vgcache_find_format(const char *vg_name); -struct list *vgcache_find_by_vgid(const char *vgid); - -/* FIXME Temporary function */ -char *vgname_from_vgid(struct cmd_context *cmd, struct id *vgid); - -/* Add/delete a device */ -int vgcache_add(const char *vg_name, const char *vgid, struct device *dev, - struct format_type *fmt); -void vgcache_del(const char *vg_name); - -#endif