mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
175 lines
3.0 KiB
C
175 lines
3.0 KiB
C
/*
|
|
* Copyright (C) 2001 Sistina Software
|
|
*
|
|
* This file is released under the LGPL.
|
|
*/
|
|
|
|
#include "pv_map.h"
|
|
#include "log.h"
|
|
|
|
|
|
static int _create_maps(struct pool *mem, struct list *pvs, struct list *maps)
|
|
{
|
|
struct list *tmp;
|
|
struct physical_volume *pv;
|
|
struct pv_map *pvm;
|
|
|
|
list_iterate(tmp, pvs) {
|
|
pv = &(list_item(tmp, struct pv_list)->pv);
|
|
|
|
if (!(pvm = pool_zalloc(mem, sizeof(*pvm)))) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
pvm->pv = pv;
|
|
if (!(pvm->allocated_extents =
|
|
bitset_create(mem, pv->pe_count))) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
list_add(maps, &pvm->list);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int _fill_bitsets(struct volume_group *vg, struct list *maps)
|
|
{
|
|
/*
|
|
* FIXME: should put pvm's in a table for
|
|
* O(1) access, and remove the nasty inner
|
|
* loop in this code.
|
|
*/
|
|
struct list *lvh, *pvmh;
|
|
struct logical_volume *lv;
|
|
struct pe_specifier *pes;
|
|
struct pv_map *pvm;
|
|
uint32_t le;
|
|
|
|
list_iterate(lvh, &vg->lvs) {
|
|
lv = &(list_item(lvh, struct lv_list)->lv);
|
|
|
|
for (le = 0; le < lv->le_count; le++) {
|
|
pes = lv->map + le;
|
|
|
|
/* this is the nasty that will kill performance */
|
|
list_iterate(pvmh, maps) {
|
|
pvm = list_item(pvmh, struct pv_map);
|
|
|
|
if (pvm->pv == pes->pv)
|
|
break;
|
|
}
|
|
|
|
/* not all pvs are necc. in the list */
|
|
if (pvmh == maps)
|
|
continue;
|
|
|
|
bit_set(pvm->allocated_extents, pes->pe);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int _create_single_area(struct pool *mem, struct pv_map *pvm,
|
|
uint32_t *extent)
|
|
{
|
|
uint32_t e = *extent, b, count = pvm->pv->pe_count;
|
|
struct pv_area *pva;
|
|
|
|
while (e < count && bit(pvm->allocated_extents, e))
|
|
e++;
|
|
|
|
if (e == count) {
|
|
*extent = e;
|
|
return 1;
|
|
}
|
|
|
|
b = e++;
|
|
|
|
while (e < count && !bit(pvm->allocated_extents, e))
|
|
e++;
|
|
|
|
if (!(pva = pool_zalloc(mem, sizeof(*pva)))) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
list_init(&pvm->areas);
|
|
pva->start = b;
|
|
pva->count = e - b;
|
|
list_add(&pvm->areas, &pva->list);
|
|
*extent = e;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int _create_areas(struct pool *mem, struct pv_map *pvm)
|
|
{
|
|
uint32_t pe = 0;
|
|
|
|
while (pe < pvm->pv->pe_count)
|
|
if (!_create_single_area(mem, pvm, &pe)) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int _create_all_areas(struct pool *mem, struct list *maps)
|
|
{
|
|
struct list *tmp;
|
|
struct pv_map *pvm;
|
|
|
|
list_iterate(tmp, maps) {
|
|
pvm = list_item(tmp, struct pv_map);
|
|
|
|
if (!_create_areas(mem, pvm)) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
struct list *create_pv_maps(struct pool *mem, struct volume_group *vg,
|
|
struct list *pvs)
|
|
{
|
|
struct list *maps = pool_zalloc(mem, sizeof(*maps));
|
|
|
|
if (!maps) {
|
|
stack;
|
|
return NULL;
|
|
}
|
|
|
|
list_init(maps);
|
|
|
|
if (!_create_maps(mem, pvs, maps)) {
|
|
log_error("Couldn't create physical volume maps in %s",
|
|
vg->name);
|
|
goto bad;
|
|
}
|
|
|
|
if (!_fill_bitsets(vg, maps)) {
|
|
log_error("Couldn't fill extent allocation bitmaps in %s",
|
|
vg->name);
|
|
goto bad;
|
|
}
|
|
|
|
if (!_create_all_areas(mem, maps)) {
|
|
log_error("Couldn't create area maps in %s", vg->name);
|
|
goto bad;
|
|
}
|
|
|
|
return maps;
|
|
|
|
bad:
|
|
pool_free(mem, maps);
|
|
return NULL;
|
|
}
|
|
|