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);
|
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) \
|
#define list_item(v, t) \
|
||||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
((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 */
|
/* 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_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
|
#endif
|
||||||
|
@ -321,7 +321,6 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
|||||||
_inc_indent(f);
|
_inc_indent(f);
|
||||||
|
|
||||||
list_iterate(pvh, &vg->pvs) {
|
list_iterate(pvh, &vg->pvs) {
|
||||||
|
|
||||||
pv = list_item(pvh, struct pv_list)->pv;
|
pv = list_item(pvh, struct pv_list)->pv;
|
||||||
|
|
||||||
if (!(name = _get_pv_name(f, 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)
|
static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *lvh, *segh;
|
struct list *lvh;
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
@ -571,9 +570,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
|||||||
f->nl(f);
|
f->nl(f);
|
||||||
|
|
||||||
seg_count = 1;
|
seg_count = 1;
|
||||||
list_iterate(segh, &lv->segments) {
|
list_iterate_items(seg, &lv->segments) {
|
||||||
seg = list_item(segh, struct lv_segment);
|
|
||||||
|
|
||||||
if (!_print_segment(f, vg, seg_count++, seg)) {
|
if (!_print_segment(f, vg, seg_count++, seg)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
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 "pv_map.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
|
#include "lv_alloc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions adjust the pe counts in pv's
|
* 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;
|
struct lv_segment *seg;
|
||||||
uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0]));
|
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)
|
if (smallest < area_len)
|
||||||
area_len = smallest;
|
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.");
|
log_err("Couldn't allocate new stripe segment.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -188,7 +189,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
|
|||||||
if (count > remaining)
|
if (count > remaining)
|
||||||
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.");
|
log_err("Couldn't allocate new stripe segment.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -224,7 +225,7 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
|
|||||||
if (count > remaining)
|
if (count > remaining)
|
||||||
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.");
|
log_err("Couldn't allocate new mirrored segment.");
|
||||||
return 0;
|
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;
|
lv = list_item(lvh, struct lv_list)->lv;
|
||||||
if (!lock_vol(cmd, lv->lvid.s, flags)) {
|
if (!lock_vol(cmd, lv->lvid.s, flags)) {
|
||||||
log_error("Failed to lock %s", lv->name);
|
log_error("Failed to lock %s", lv->name);
|
||||||
/* FIXME Only unlock the locked ones */
|
list_uniterate(lvh, lvs, lvh) {
|
||||||
unlock_lvs(cmd, lvs);
|
lv = list_item(lvh, struct lv_list)->lv;
|
||||||
|
unlock_lv(cmd, lv->lvid.s);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
#include "toolcontext.h"
|
||||||
|
#include "lv_alloc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test whether two segments could be merged by the current merging code
|
* 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;
|
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);
|
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.
|
* 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);
|
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) \
|
#define list_item(v, t) \
|
||||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
((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 */
|
/* 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_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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user