mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
A new cache.
This commit is contained in:
parent
34917a5373
commit
74b27447c1
491
lib/cache/cache.c
vendored
Normal file
491
lib/cache/cache.c
vendored
Normal file
@ -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);
|
||||
}
|
73
lib/cache/cache.h
vendored
Normal file
73
lib/cache/cache.h
vendored
Normal file
@ -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 <sys/types.h>
|
||||
|
||||
#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
|
@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
@ -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 <sys/types.h>
|
||||
#include <asm/page.h>
|
||||
#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
|
Loading…
Reference in New Issue
Block a user