1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-02-25 21:57:45 +03:00

o Non-caching implementation of new vgcache interface.

This commit is contained in:
Joe Thornber 2002-01-14 11:43:52 +00:00
parent 9056f65b0c
commit 406d287ae1
2 changed files with 146 additions and 178 deletions

View File

@ -1,181 +1,139 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
* Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*
*/
#include <stdlib.h>
#include "vgcache.h"
#include "hash.h"
#include "label.h"
#include "dbg_malloc.h"
#include "log.h"
#include "lvm1_label.h"
static struct hash_table *_vghash;
static struct hash_table *_pvhash;
const char *all_devices = "\0";
/*
* Non-caching implementation.
* FIXME: write caching version, when thought about it a bit more.
*/
struct vg_cache {
struct dev_filter *filter;
};
int vgcache_init()
struct vg_cache *vg_cache_create(struct dev_filter *devices)
{
if (!(_vghash = hash_create(128)))
return 0;
struct vg_cache *vgc;
if (!(_pvhash = hash_create(128)))
return 0;
if (!(vgc = dbg_malloc(sizeof(*vgc)))) {
log_err("Couldn't allocate vg_cache object.");
return NULL;
}
vgc->filter = devices;
return vgc;
}
void vg_cache_destroy(struct vg_cache *vgc)
{
dbg_free(vgc);
}
struct device *vg_cache_find_uuid(struct vg_cache *vgc, struct id *id)
{
struct dev_iter *iter;
struct device *dev;
struct label *lab;
if (!(iter = dev_iter_create(vgc->filter))) {
stack;
return NULL;
}
while ((dev = dev_iter_get(iter))) {
if (label_read(dev, &lab))
continue;
if (!strcmp(lab->volume_type, "lvm") && id_equal(id, &lab->id))
break;
label_destroy(lab);
}
dev_iter_destroy(iter);
return dev;
}
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;
while ((dev = dev_iter_get(iter))) {
if (!label_read(dev, &lab))
continue;
if (strcmp(lab->volume_type, "lvm"))
continue;
info = (struct lvm_label_info *) lab->extra_info;
if (!vg || strcmp(info->volume_group, vg)) {
/* add dev to the result list */
if (!(dev_list = pool_alloc(mem, sizeof(*dev_list)))) {
stack;
label_destroy(lab);
return;
}
dev_list->dev = dev;
list_add(results, &dev_list->list);
}
label_destroy(lab);
}
}
struct list *vg_cache_find_vg(struct vg_cache *vgc, struct pool *mem,
const char *vg)
{
struct dev_iter *iter;
struct list *r;
if (!(r = pool_alloc(mem, sizeof(r)))) {
stack;
return NULL;
}
list_init(r);
if (!(iter = dev_iter_create(vgc->filter))) {
stack;
pool_free(mem, r);
return NULL;
}
_find_pvs_in_vg(vgc, mem, vg, iter, r);
dev_iter_destroy(iter);
return r;
}
int vg_cache_update_vg(struct volume_group *vg)
{
/* no-ops in a non caching version */
return 1;
}
/* A vg_name of NULL returns all_devices */
struct list *vgcache_find(const char *vg_name)
int vg_cache_update_device(struct device *dev)
{
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;
}
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, struct device *dev)
{
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;
}
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;
}
}
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;
}
/* no-ops in a non caching version */
return 1;
}
/* 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;
/* If orphan PV remove it */
if (vg_name && !*vg_name)
vgcache_del_orphan(dev);
/* Add PV if vg_name supplied */
if (vg_name && *vg_name && !vgcache_add_entry(vg_name, dev))
return 0;
/* Always add to all_devices */
return vgcache_add_entry(all_devices, dev);
}
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);
}
dbg_free(vgn->vgname);
}
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);
vgcache_destroy_entry(vgn);
}
void vgcache_destroy()
{
if (_vghash) {
hash_iterate(_vghash, (iterate_fn)vgcache_destroy_entry);
hash_destroy(_vghash);
_vghash = NULL;
}
if (_pvhash) {
hash_destroy(_pvhash);
_pvhash = NULL;
}
}

View File

@ -8,29 +8,39 @@
#ifndef _LVM_VGCACHE_H
#define _LVM_VGCACHE_H
#include <sys/types.h>
#include <asm/page.h>
#include "dev-cache.h"
#include "vgcache.h"
#include "list.h"
#include "uuid.h"
#include "pool.h"
#include "dev-cache.h"
#include "metadata.h"
struct vgname_entry {
struct list pvdevs;
char *vgname;
};
struct pvdev_list {
struct list list;
struct device *dev;
};
/*
* Maintains a register of LVM specific information about
* devices. Makes use of the label code.
*/
struct vg_cache;
int vgcache_init();
void vgcache_destroy();
struct vg_cache *vg_cache_create(struct dev_filter *devices);
void vg_cache_destroy(struct vg_cache *vgc);
/* Return list of PVs in named VG */
struct list *vgcache_find(const char *vg_name);
/*
* Find the device with a particular uuid.
*/
struct device *vg_cache_find_uuid(struct vg_cache *vgc, struct id *id);
/* Add/delete a device */
int vgcache_add(const char *vg_name, struct device *dev);
void vgcache_del(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);
#endif