mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Improve segment merge/split code.
This commit is contained in:
parent
a7617ea224
commit
85c1926171
@ -63,26 +63,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#define list_item(v, t) \
|
||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
||||
|
||||
@ -96,4 +76,28 @@ static inline unsigned int list_size(const struct list *head)
|
||||
/* Given a known element in a known structure, locate the list head */
|
||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
#define list_iterate_items(v, head) \
|
||||
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
|
||||
v = list_item(v->list.n, typeof(*v)))
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -321,7 +321,6 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
_inc_indent(f);
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
|
||||
if (!(name = _get_pv_name(f, pv))) {
|
||||
@ -522,7 +521,7 @@ static int _print_snapshots(struct formatter *f, struct volume_group *vg)
|
||||
|
||||
static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh, *segh;
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *seg;
|
||||
char buffer[256];
|
||||
@ -571,9 +570,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
f->nl(f);
|
||||
|
||||
seg_count = 1;
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_print_segment(f, vg, seg_count++, seg)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
14
lib/metadata/lv_alloc.h
Normal file
14
lib/metadata/lv_alloc.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Sistina Software (UK) Limited.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
*
|
||||
* This is the in core representation of a volume group and its
|
||||
* associated physical and logical volumes.
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LV_ALLOC_H
|
||||
#include "pool.h"
|
||||
|
||||
struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t stripes);
|
||||
#endif
|
@ -10,6 +10,7 @@
|
||||
#include "pv_map.h"
|
||||
#include "lvm-string.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lv_alloc.h"
|
||||
|
||||
/*
|
||||
* These functions adjust the pe counts in pv's
|
||||
@ -49,7 +50,7 @@ static void _put_extents(struct lv_segment *seg)
|
||||
}
|
||||
}
|
||||
|
||||
static struct lv_segment *_alloc_segment(struct pool *mem, uint32_t stripes)
|
||||
struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t stripes)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0]));
|
||||
@ -75,7 +76,7 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
|
||||
if (smallest < area_len)
|
||||
area_len = smallest;
|
||||
|
||||
if (!(seg = _alloc_segment(lv->vg->cmd->mem, stripes))) {
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, stripes))) {
|
||||
log_err("Couldn't allocate new stripe segment.");
|
||||
return 0;
|
||||
}
|
||||
@ -188,7 +189,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
|
||||
if (count > remaining)
|
||||
count = remaining;
|
||||
|
||||
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 1))) {
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 1))) {
|
||||
log_err("Couldn't allocate new stripe segment.");
|
||||
return 0;
|
||||
}
|
||||
@ -224,7 +225,7 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
|
||||
if (count > remaining)
|
||||
count = remaining;
|
||||
|
||||
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 2))) {
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 2))) {
|
||||
log_err("Couldn't allocate new mirrored segment.");
|
||||
return 0;
|
||||
}
|
||||
@ -731,8 +732,11 @@ int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!lock_vol(cmd, lv->lvid.s, flags)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
/* FIXME Only unlock the locked ones */
|
||||
unlock_lvs(cmd, lvs);
|
||||
list_uniterate(lvh, lvs, lvh) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
unlock_lv(cmd, lv->lvid.s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "lib.h"
|
||||
#include "metadata.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lv_alloc.h"
|
||||
|
||||
/*
|
||||
* Test whether two segments could be merged by the current merging code
|
||||
@ -100,3 +102,89 @@ int lv_check_segments(struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the supplied segment at the supplied logical extent
|
||||
*/
|
||||
static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
uint32_t le)
|
||||
{
|
||||
size_t len;
|
||||
struct lv_segment *split_seg;
|
||||
uint32_t s;
|
||||
uint32_t offset = le - seg->le;
|
||||
|
||||
if (seg->type == SEG_SNAPSHOT) {
|
||||
log_error("Unable to split the snapshot segment at LE %" PRIu32
|
||||
" in LV %s", le, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clone the existing segment */
|
||||
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem,
|
||||
seg->area_count))) {
|
||||
log_error("Couldn't allocate new LV segment.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = sizeof(*seg) + (seg->area_count * sizeof(seg->area[0]));
|
||||
memcpy(split_seg, seg, len);
|
||||
|
||||
/* In case of a striped segment, the offset has to be / stripes */
|
||||
if (seg->type == SEG_STRIPED)
|
||||
offset /= seg->area_count;
|
||||
|
||||
/* Adjust the PV mapping */
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
/* Split area at the offset */
|
||||
switch (seg->area[s].type) {
|
||||
case AREA_LV:
|
||||
split_seg->area[s].u.lv.le =
|
||||
seg->area[s].u.lv.le + offset;
|
||||
break;
|
||||
|
||||
case AREA_PV:
|
||||
split_seg->area[s].u.pv.pe =
|
||||
seg->area[s].u.pv.pe + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unrecognised segment type %u",
|
||||
seg->area[s].type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
split_seg->area_len = seg->area_len - offset;
|
||||
seg->area_len = offset;
|
||||
|
||||
/* Add split off segment to the list _after_ the original one */
|
||||
list_add_h(&seg->list, &split_seg->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure there's a segment boundary at the given logical extent
|
||||
*/
|
||||
int lv_split_segment(struct logical_volume *lv, uint32_t le)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
|
||||
if (!(seg = find_seg_by_le(lv, le))) {
|
||||
log_error("Segment with extent %" PRIu32 " in LV %s not found",
|
||||
le, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a segment start already */
|
||||
if (le == seg->le)
|
||||
return 1;
|
||||
|
||||
if (!_lv_split_segment(lv, seg, le)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -468,6 +468,11 @@ int lv_check_segments(struct logical_volume *lv);
|
||||
*/
|
||||
int lv_merge_segments(struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* Ensure there's a segment boundary at a given LE, splitting if necessary
|
||||
*/
|
||||
int lv_split_segment(struct logical_volume *lv, uint32_t le);
|
||||
|
||||
/*
|
||||
* Useful functions for managing snapshots.
|
||||
*/
|
||||
|
@ -63,26 +63,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#define list_item(v, t) \
|
||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
||||
|
||||
@ -96,4 +76,28 @@ static inline unsigned int list_size(const struct list *head)
|
||||
/* Given a known element in a known structure, locate the list head */
|
||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
#define list_iterate_items(v, head) \
|
||||
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
|
||||
v = list_item(v->list.n, typeof(*v)))
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user