mirror of
git://sourceware.org/git/lvm2.git
synced 2025-02-02 13:47:42 +03:00
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 *
This commit is contained in:
parent
49588ccd98
commit
1ca18f501a
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -22,6 +22,11 @@ struct device {
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct device_list {
|
||||
struct list list;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
/*
|
||||
* All io should use these routines.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
70
lib/label/uuid-map.c
Normal file
70
lib/label/uuid-map.c
Normal file
@ -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
|
26
lib/label/uuid-map.h
Normal file
26
lib/label/uuid-map.h
Normal file
@ -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
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 <stdlib.h>
|
||||
|
||||
#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 (!(vgc = dbg_malloc(sizeof(*vgc)))) {
|
||||
log_err("Couldn't allocate vg_cache object.");
|
||||
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;
|
||||
}
|
||||
|
||||
vgc->filter = devices;
|
||||
if (!vg_name)
|
||||
vg_name = all_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;
|
||||
if (!(vgn = hash_lookup(_vghash, vg_name)))
|
||||
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;
|
||||
return &vgn->pvdevs;
|
||||
}
|
||||
|
||||
static void _find_pvs_in_vg(struct vg_cache *vgc, struct pool *mem,
|
||||
const char *vg, struct dev_iter *iter,
|
||||
struct list *results)
|
||||
void vgcache_del_orphan(struct device *dev)
|
||||
{
|
||||
struct device *dev;
|
||||
struct label *lab;
|
||||
struct device_list *dev_list;
|
||||
struct lvm_label_info *info;
|
||||
struct pvdev_list *pvdev;
|
||||
|
||||
while ((dev = dev_iter_get(iter))) {
|
||||
if (_pvhash && ((pvdev = hash_lookup(_pvhash, dev_name(dev))))) {
|
||||
list_del(&pvdev->list);
|
||||
hash_remove(_pvhash, dev_name(pvdev->dev));
|
||||
dbg_free(pvdev);
|
||||
}
|
||||
}
|
||||
|
||||
if (!label_read(dev, &lab))
|
||||
continue;
|
||||
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 (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);
|
||||
if (!(pvdevs = vgcache_find(vg_name))) {
|
||||
if (!(vgn = dbg_malloc(sizeof(struct vgname_entry)))) {
|
||||
log_error("struct vgname_entry allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
label_destroy(lab);
|
||||
}
|
||||
}
|
||||
pvdevs = &vgn->pvdevs;
|
||||
list_init(pvdevs);
|
||||
|
||||
struct list *vg_cache_find_vg(struct vg_cache *vgc, struct pool *mem,
|
||||
const char *vg)
|
||||
{
|
||||
struct dev_iter *iter;
|
||||
struct list *r;
|
||||
if (!(vgn->vgname = dbg_strdup(vg_name))) {
|
||||
log_error("vgcache_add: strdup vg_name failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
if (!hash_insert(_vghash, vg_name, vgn)) {
|
||||
log_error("vgcache_add: VG hash insertion failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_find_pvs_in_vg(vgc, mem, vg, iter, r);
|
||||
list_iterate(pvdh, pvdevs) {
|
||||
pvdev = list_item(pvdh, struct pvdev_list);
|
||||
if (dev == pvdev->dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev_iter_destroy(iter);
|
||||
return r;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
int vg_cache_update_vg(struct volume_group *vg)
|
||||
{
|
||||
/* no-ops in a non caching version */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vg_cache_update_device(struct device *dev)
|
||||
/* 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)
|
||||
{
|
||||
/* no-ops in a non caching version */
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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 <sys/types.h>
|
||||
#include <asm/page.h>
|
||||
#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
|
||||
|
Loading…
x
Reference in New Issue
Block a user