mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Extend cling allocation policy to recognise PV tags (cling_by_tags).
Add allocation/cling_tag_list to lvm.conf.
This commit is contained in:
parent
5a976864ee
commit
eb82bd0525
@ -1,5 +1,7 @@
|
|||||||
Version 2.02.77 -
|
Version 2.02.77 -
|
||||||
===================================
|
===================================
|
||||||
|
Extend cling allocation policy to recognise PV tags (cling_by_tags).
|
||||||
|
Add allocation/cling_tag_list to lvm.conf.
|
||||||
Regenerate configure with 'autoreconf' for --enable-ocf. (2.02.76)
|
Regenerate configure with 'autoreconf' for --enable-ocf. (2.02.76)
|
||||||
|
|
||||||
Version 2.02.76 - 8th November 2010
|
Version 2.02.76 - 8th November 2010
|
||||||
|
@ -146,6 +146,25 @@ devices {
|
|||||||
require_restorefile_with_uuid = 1
|
require_restorefile_with_uuid = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This section allows you to configure the way in which LVM selects
|
||||||
|
# free space for its Logical Volumes.
|
||||||
|
#allocation {
|
||||||
|
# When searching for free space to extend an LV, the "cling"
|
||||||
|
# allocation policy will choose space on the same PVs as the last
|
||||||
|
# segment of the existing LV. If there is insufficient space and a
|
||||||
|
# list of tags is defined here, it will check whether any of them are
|
||||||
|
# attached to the PVs concerned and then seek to match those PV tags
|
||||||
|
# between existing extents and new extents.
|
||||||
|
# Use the special tag "@*" as a wildcard to match any PV tag.
|
||||||
|
#
|
||||||
|
# Example: LVs are mirrored between two sites within a single VG.
|
||||||
|
# PVs are tagged with either @site1 or @site2 to indicate where
|
||||||
|
# they are situated.
|
||||||
|
#
|
||||||
|
# cling_tag_list = [ "@site1", "@site2" ]
|
||||||
|
# cling_tag_list = [ "@*" ]
|
||||||
|
#}
|
||||||
|
|
||||||
# This section that allows you to configure the nature of the
|
# This section that allows you to configure the nature of the
|
||||||
# information that LVM2 reports.
|
# information that LVM2 reports.
|
||||||
log {
|
log {
|
||||||
|
@ -275,8 +275,8 @@ static int _passes_activation_filter(struct cmd_context *cmd,
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* If any host tag matches any LV or VG tag, activate */
|
/* If any host tag matches any LV or VG tag, activate */
|
||||||
if (str_list_match_list(&cmd->tags, &lv->tags) ||
|
if (str_list_match_list(&cmd->tags, &lv->tags, NULL) ||
|
||||||
str_list_match_list(&cmd->tags, &lv->vg->tags))
|
str_list_match_list(&cmd->tags, &lv->vg->tags, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
log_verbose("No host tag matches %s/%s",
|
log_verbose("No host tag matches %s/%s",
|
||||||
@ -314,9 +314,9 @@ static int _passes_activation_filter(struct cmd_context *cmd,
|
|||||||
}
|
}
|
||||||
/* If any host tag matches any LV or VG tag, activate */
|
/* If any host tag matches any LV or VG tag, activate */
|
||||||
if (!strcmp(str, "*")) {
|
if (!strcmp(str, "*")) {
|
||||||
if (str_list_match_list(&cmd->tags, &lv->tags)
|
if (str_list_match_list(&cmd->tags, &lv->tags, NULL)
|
||||||
|| str_list_match_list(&cmd->tags,
|
|| str_list_match_list(&cmd->tags,
|
||||||
&lv->vg->tags))
|
&lv->vg->tags, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
@ -93,14 +93,18 @@ int str_list_match_item(const struct dm_list *sll, const char *str)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Is at least one item on both lists?
|
* Is at least one item on both lists?
|
||||||
|
* If tag_matched is non-NULL, it is set to the tag that matched.
|
||||||
*/
|
*/
|
||||||
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2)
|
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, char **tag_matched)
|
||||||
{
|
{
|
||||||
struct str_list *sl;
|
struct str_list *sl;
|
||||||
|
|
||||||
dm_list_iterate_items(sl, sll)
|
dm_list_iterate_items(sl, sll)
|
||||||
if (str_list_match_item(sll2, sl->str))
|
if (str_list_match_item(sll2, sl->str)) {
|
||||||
return 1;
|
if (tag_matched)
|
||||||
|
*tag_matched = sl->str;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ struct dm_list *str_list_create(struct dm_pool *mem);
|
|||||||
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
|
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
|
||||||
int str_list_del(struct dm_list *sll, const char *str);
|
int str_list_del(struct dm_list *sll, const char *str);
|
||||||
int str_list_match_item(const struct dm_list *sll, const char *str);
|
int str_list_match_item(const struct dm_list *sll, const char *str);
|
||||||
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2);
|
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, char **tag_matched);
|
||||||
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
|
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
|
||||||
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
|
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
|
||||||
const struct dm_list *sllold);
|
const struct dm_list *sllold);
|
||||||
|
@ -26,12 +26,13 @@ typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
|
|||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
alloc_policy_t alloc;
|
alloc_policy_t alloc;
|
||||||
const char str[12]; /* must be changed when size extends 11 chars */
|
const char str[14]; /* must be changed when size extends 13 chars */
|
||||||
const char repchar;
|
const char repchar;
|
||||||
} _policies[] = {
|
} _policies[] = {
|
||||||
{
|
{
|
||||||
ALLOC_CONTIGUOUS, "contiguous", 'c'}, {
|
ALLOC_CONTIGUOUS, "contiguous", 'c'}, {
|
||||||
ALLOC_CLING, "cling", 'l'}, {
|
ALLOC_CLING, "cling", 'l'}, {
|
||||||
|
ALLOC_CLING_BY_TAGS, "cling_by_tags", 't'}, { /* Only used in log mesgs */
|
||||||
ALLOC_NORMAL, "normal", 'n'}, {
|
ALLOC_NORMAL, "normal", 'n'}, {
|
||||||
ALLOC_ANYWHERE, "anywhere", 'a'}, {
|
ALLOC_ANYWHERE, "anywhere", 'a'}, {
|
||||||
ALLOC_INHERIT, "inherit", 'i'}
|
ALLOC_INHERIT, "inherit", 'i'}
|
||||||
@ -147,12 +148,16 @@ alloc_policy_t get_alloc_from_string(const char *str)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* cling_by_tags is part of cling */
|
||||||
|
if (!strcmp("cling_by_tags", str))
|
||||||
|
return ALLOC_CLING;
|
||||||
|
|
||||||
for (i = 0; i < _num_policies; i++)
|
for (i = 0; i < _num_policies; i++)
|
||||||
if (!strcmp(_policies[i].str, str))
|
if (!strcmp(_policies[i].str, str))
|
||||||
return _policies[i].alloc;
|
return _policies[i].alloc;
|
||||||
|
|
||||||
/* Special case for old metadata */
|
/* Special case for old metadata */
|
||||||
if(!strcmp("next free", str))
|
if (!strcmp("next free", str))
|
||||||
return ALLOC_NORMAL;
|
return ALLOC_NORMAL;
|
||||||
|
|
||||||
log_error("Unrecognised allocation policy %s", str);
|
log_error("Unrecognised allocation policy %s", str);
|
||||||
|
@ -526,6 +526,8 @@ struct alloc_handle {
|
|||||||
uint32_t region_size; /* Mirror region size */
|
uint32_t region_size; /* Mirror region size */
|
||||||
uint32_t total_area_len; /* Total number of parallel extents */
|
uint32_t total_area_len; /* Total number of parallel extents */
|
||||||
|
|
||||||
|
const struct config_node *cling_tag_list_cn;
|
||||||
|
|
||||||
struct dm_list *parallel_areas; /* PVs to avoid */
|
struct dm_list *parallel_areas; /* PVs to avoid */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -640,6 +642,8 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
|
|||||||
|
|
||||||
ah->parallel_areas = parallel_areas;
|
ah->parallel_areas = parallel_areas;
|
||||||
|
|
||||||
|
ah->cling_tag_list_cn = find_config_tree_node(cmd, "allocation/cling_tag_list");
|
||||||
|
|
||||||
return ah;
|
return ah;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -927,18 +931,19 @@ static int _comp_area(const void *l, const void *r)
|
|||||||
* Search for pvseg that matches condition
|
* Search for pvseg that matches condition
|
||||||
*/
|
*/
|
||||||
struct pv_match {
|
struct pv_match {
|
||||||
int (*condition)(struct pv_segment *pvseg, struct pv_area *pva);
|
int (*condition)(struct pv_match *pvmatch, struct pv_segment *pvseg, struct pv_area *pva);
|
||||||
|
|
||||||
struct pv_area_used *areas;
|
struct pv_area_used *areas;
|
||||||
struct pv_area *pva;
|
struct pv_area *pva;
|
||||||
uint32_t areas_size;
|
uint32_t areas_size;
|
||||||
|
const struct config_node *cling_tag_list_cn;
|
||||||
int s; /* Area index of match */
|
int s; /* Area index of match */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is PV area on the same PV?
|
* Is PV area on the same PV?
|
||||||
*/
|
*/
|
||||||
static int _is_same_pv(struct pv_segment *pvseg, struct pv_area *pva)
|
static int _is_same_pv(struct pv_match *pvmatch __attribute((unused)), struct pv_segment *pvseg, struct pv_area *pva)
|
||||||
{
|
{
|
||||||
if (pvseg->pv != pva->map->pv)
|
if (pvseg->pv != pva->map->pv)
|
||||||
return 0;
|
return 0;
|
||||||
@ -946,10 +951,71 @@ static int _is_same_pv(struct pv_segment *pvseg, struct pv_area *pva)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does PV area have a tag listed in allocation/cling_tag_list that
|
||||||
|
* matches a tag of the PV of the existing segment?
|
||||||
|
*/
|
||||||
|
static int _has_matching_pv_tag(struct pv_match *pvmatch, struct pv_segment *pvseg, struct pv_area *pva)
|
||||||
|
{
|
||||||
|
struct config_value *cv;
|
||||||
|
char *str;
|
||||||
|
char *tag_matched;
|
||||||
|
|
||||||
|
for (cv = pvmatch->cling_tag_list_cn->v; cv; cv = cv->next) {
|
||||||
|
if (cv->type != CFG_STRING) {
|
||||||
|
log_error("Ignoring invalid string in config file entry "
|
||||||
|
"allocation/cling_tag_list");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str = cv->v.str;
|
||||||
|
if (!*str) {
|
||||||
|
log_error("Ignoring empty string in config file entry "
|
||||||
|
"allocation/cling_tag_list");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str != '@') {
|
||||||
|
log_error("Ignoring string not starting with @ in config file entry "
|
||||||
|
"allocation/cling_tag_list: %s", str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
str++;
|
||||||
|
|
||||||
|
if (!*str) {
|
||||||
|
log_error("Ignoring empty tag in config file entry "
|
||||||
|
"allocation/cling_tag_list");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wildcard matches any tag against any tag. */
|
||||||
|
if (!strcmp(str, "*")) {
|
||||||
|
if (!str_list_match_list(&pvseg->pv->tags, &pva->map->pv->tags, &tag_matched))
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
log_debug("Matched allocation PV tag %s on existing %s with free space on %s.",
|
||||||
|
tag_matched, pv_dev_name(pvseg->pv), pv_dev_name(pva->map->pv));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!str_list_match_item(&pvseg->pv->tags, str) ||
|
||||||
|
!str_list_match_item(&pva->map->pv->tags, str))
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
log_debug("Matched allocation PV tag %s on existing %s with free space on %s.",
|
||||||
|
str, pv_dev_name(pvseg->pv), pv_dev_name(pva->map->pv));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is PV area contiguous to PV segment?
|
* Is PV area contiguous to PV segment?
|
||||||
*/
|
*/
|
||||||
static int _is_contiguous(struct pv_segment *pvseg, struct pv_area *pva)
|
static int _is_contiguous(struct pv_match *pvmatch __attribute((unused)), struct pv_segment *pvseg, struct pv_area *pva)
|
||||||
{
|
{
|
||||||
if (pvseg->pv != pva->map->pv)
|
if (pvseg->pv != pva->map->pv)
|
||||||
return 0;
|
return 0;
|
||||||
@ -966,7 +1032,7 @@ static int _is_condition(struct cmd_context *cmd __attribute__((unused)),
|
|||||||
{
|
{
|
||||||
struct pv_match *pvmatch = data;
|
struct pv_match *pvmatch = data;
|
||||||
|
|
||||||
if (!pvmatch->condition(pvseg, pvmatch->pva))
|
if (!pvmatch->condition(pvmatch, pvseg, pvmatch->pva))
|
||||||
return 1; /* Continue */
|
return 1; /* Continue */
|
||||||
|
|
||||||
if (s >= pvmatch->areas_size)
|
if (s >= pvmatch->areas_size)
|
||||||
@ -991,16 +1057,18 @@ static int _is_condition(struct cmd_context *cmd __attribute__((unused)),
|
|||||||
* Is pva on same PV as any existing areas?
|
* Is pva on same PV as any existing areas?
|
||||||
*/
|
*/
|
||||||
static int _check_cling(struct cmd_context *cmd,
|
static int _check_cling(struct cmd_context *cmd,
|
||||||
|
const struct config_node *cling_tag_list_cn,
|
||||||
struct lv_segment *prev_lvseg, struct pv_area *pva,
|
struct lv_segment *prev_lvseg, struct pv_area *pva,
|
||||||
struct pv_area_used *areas, uint32_t areas_size)
|
struct pv_area_used *areas, uint32_t areas_size)
|
||||||
{
|
{
|
||||||
struct pv_match pvmatch;
|
struct pv_match pvmatch;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
pvmatch.condition = _is_same_pv;
|
pvmatch.condition = cling_tag_list_cn ? _has_matching_pv_tag : _is_same_pv;
|
||||||
pvmatch.areas = areas;
|
pvmatch.areas = areas;
|
||||||
pvmatch.areas_size = areas_size;
|
pvmatch.areas_size = areas_size;
|
||||||
pvmatch.pva = pva;
|
pvmatch.pva = pva;
|
||||||
|
pvmatch.cling_tag_list_cn = cling_tag_list_cn;
|
||||||
|
|
||||||
/* FIXME Cope with stacks by flattening */
|
/* FIXME Cope with stacks by flattening */
|
||||||
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
|
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
|
||||||
@ -1029,6 +1097,7 @@ static int _check_contiguous(struct cmd_context *cmd,
|
|||||||
pvmatch.areas = areas;
|
pvmatch.areas = areas;
|
||||||
pvmatch.areas_size = areas_size;
|
pvmatch.areas_size = areas_size;
|
||||||
pvmatch.pva = pva;
|
pvmatch.pva = pva;
|
||||||
|
pvmatch.cling_tag_list_cn = NULL;
|
||||||
|
|
||||||
/* FIXME Cope with stacks by flattening */
|
/* FIXME Cope with stacks by flattening */
|
||||||
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
|
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
|
||||||
@ -1056,7 +1125,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
|||||||
struct pv_area *pva;
|
struct pv_area *pva;
|
||||||
struct pv_list *pvl;
|
struct pv_list *pvl;
|
||||||
unsigned already_found_one = 0;
|
unsigned already_found_one = 0;
|
||||||
unsigned contiguous = 0, cling = 0, preferred_count = 0;
|
unsigned contiguous = 0, cling = 0, use_cling_tags = 0, preferred_count = 0;
|
||||||
unsigned ix, last_ix;
|
unsigned ix, last_ix;
|
||||||
unsigned ix_offset = 0; /* Offset for non-preferred allocations */
|
unsigned ix_offset = 0; /* Offset for non-preferred allocations */
|
||||||
unsigned ix_log_offset; /* Offset to start of areas to use for log */
|
unsigned ix_log_offset; /* Offset to start of areas to use for log */
|
||||||
@ -1089,7 +1158,10 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
|||||||
contiguous = 1;
|
contiguous = 1;
|
||||||
else if ((alloc == ALLOC_CLING))
|
else if ((alloc == ALLOC_CLING))
|
||||||
cling = 1;
|
cling = 1;
|
||||||
else
|
else if ((alloc == ALLOC_CLING_BY_TAGS)) {
|
||||||
|
cling = 1;
|
||||||
|
use_cling_tags = 1;
|
||||||
|
} else
|
||||||
ix_offset = 0;
|
ix_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,9 +1248,10 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
|||||||
if (cling) {
|
if (cling) {
|
||||||
if (prev_lvseg &&
|
if (prev_lvseg &&
|
||||||
_check_cling(ah->cmd,
|
_check_cling(ah->cmd,
|
||||||
prev_lvseg,
|
use_cling_tags ? ah->cling_tag_list_cn : NULL,
|
||||||
pva, *areas_ptr,
|
prev_lvseg,
|
||||||
*areas_size_ptr)) {
|
pva, *areas_ptr,
|
||||||
|
*areas_size_ptr)) {
|
||||||
preferred_count++;
|
preferred_count++;
|
||||||
}
|
}
|
||||||
goto next_pv;
|
goto next_pv;
|
||||||
@ -1361,8 +1434,18 @@ static int _allocate(struct alloc_handle *ah,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cling includes implicit cling_by_tags
|
||||||
|
* but it does nothing unless the lvm.conf setting is present.
|
||||||
|
*/
|
||||||
|
if (ah->alloc == ALLOC_CLING)
|
||||||
|
ah->alloc = ALLOC_CLING_BY_TAGS;
|
||||||
|
|
||||||
/* Attempt each defined allocation policy in turn */
|
/* Attempt each defined allocation policy in turn */
|
||||||
for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
|
for (alloc = ALLOC_CONTIGUOUS; alloc < ALLOC_INHERIT; alloc++) {
|
||||||
|
/* Skip cling_by_tags if no list defined */
|
||||||
|
if (alloc == ALLOC_CLING_BY_TAGS && !ah->cling_tag_list_cn)
|
||||||
|
continue;
|
||||||
old_allocated = allocated;
|
old_allocated = allocated;
|
||||||
log_debug("Trying allocation using %s policy. "
|
log_debug("Trying allocation using %s policy. "
|
||||||
"Need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log areas of %" PRIu32 " extents. "
|
"Need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log areas of %" PRIu32 " extents. "
|
||||||
@ -1829,8 +1912,8 @@ static int _rename_sub_lv(struct cmd_context *cmd,
|
|||||||
/*
|
/*
|
||||||
* Compose a new name for sub lv:
|
* Compose a new name for sub lv:
|
||||||
* e.g. new name is "lvol1_mlog"
|
* e.g. new name is "lvol1_mlog"
|
||||||
* if the sub LV is "lvol0_mlog" and
|
* if the sub LV is "lvol0_mlog" and
|
||||||
* a new name for main LV is "lvol1"
|
* a new name for main LV is "lvol1"
|
||||||
*/
|
*/
|
||||||
len = strlen(lv_name_new) + strlen(suffix) + 1;
|
len = strlen(lv_name_new) + strlen(suffix) + 1;
|
||||||
new_name = dm_pool_alloc(cmd->mem, len);
|
new_name = dm_pool_alloc(cmd->mem, len);
|
||||||
@ -2339,7 +2422,7 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lv_remove_single(cmd, lv, force);
|
return lv_remove_single(cmd, lv, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2164,6 +2164,12 @@ int vg_validate(struct volume_group *vg)
|
|||||||
uint32_t num_snapshots = 0;
|
uint32_t num_snapshots = 0;
|
||||||
uint32_t loop_counter1, loop_counter2;
|
uint32_t loop_counter1, loop_counter2;
|
||||||
|
|
||||||
|
if (vg->alloc == ALLOC_CLING_BY_TAGS) {
|
||||||
|
log_error(INTERNAL_ERROR "VG %s allocation policy set to invalid cling_by_tags.",
|
||||||
|
vg->name);
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME Also check there's no data/metadata overlap */
|
/* FIXME Also check there's no data/metadata overlap */
|
||||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||||
if (++pv_count > vg->pv_count) {
|
if (++pv_count > vg->pv_count) {
|
||||||
@ -2233,6 +2239,12 @@ int vg_validate(struct volume_group *vg)
|
|||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lvl->lv->alloc == ALLOC_CLING_BY_TAGS) {
|
||||||
|
log_error(INTERNAL_ERROR "LV %s allocation policy set to invalid cling_by_tags.",
|
||||||
|
lvl->lv->name);
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (lvl->lv->status & VISIBLE_LV)
|
if (lvl->lv->status & VISIBLE_LV)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ static int _delete_lv(struct logical_volume *mirror_lv, struct logical_volume *l
|
|||||||
struct str_list *sl;
|
struct str_list *sl;
|
||||||
|
|
||||||
/* Inherit tags - maybe needed for activation */
|
/* Inherit tags - maybe needed for activation */
|
||||||
if (!str_list_match_list(&mirror_lv->tags, &lv->tags)) {
|
if (!str_list_match_list(&mirror_lv->tags, &lv->tags, NULL)) {
|
||||||
dm_list_iterate_items(sl, &mirror_lv->tags)
|
dm_list_iterate_items(sl, &mirror_lv->tags)
|
||||||
if (!str_list_add(cmd->mem, &lv->tags, sl->str)) {
|
if (!str_list_add(cmd->mem, &lv->tags, sl->str)) {
|
||||||
log_error("Aborting. Unable to tag.");
|
log_error("Aborting. Unable to tag.");
|
||||||
|
@ -25,6 +25,7 @@ typedef enum {
|
|||||||
ALLOC_INVALID,
|
ALLOC_INVALID,
|
||||||
ALLOC_CONTIGUOUS,
|
ALLOC_CONTIGUOUS,
|
||||||
ALLOC_CLING,
|
ALLOC_CLING,
|
||||||
|
ALLOC_CLING_BY_TAGS, /* Internal - never written or displayed. */
|
||||||
ALLOC_NORMAL,
|
ALLOC_NORMAL,
|
||||||
ALLOC_ANYWHERE,
|
ALLOC_ANYWHERE,
|
||||||
ALLOC_INHERIT
|
ALLOC_INHERIT
|
||||||
|
@ -172,6 +172,28 @@ the limit set here, no further I/O is sent to that device for the remainder of
|
|||||||
the respective operation. Setting the parameter to 0 disables the counters
|
the respective operation. Setting the parameter to 0 disables the counters
|
||||||
altogether.
|
altogether.
|
||||||
.TP
|
.TP
|
||||||
|
\fBallocation\fP \(em Space allocation policies
|
||||||
|
.IP
|
||||||
|
\fBcling_tag_list\fP \(em List of PV tags matched by the \fBcling\fP allocation policy.
|
||||||
|
.IP
|
||||||
|
When searching for free space to extend an LV, the \fBcling\fP
|
||||||
|
allocation policy will choose space on the same PVs as the last
|
||||||
|
segment of the existing LV. If there is insufficient space and a
|
||||||
|
list of tags is defined here, it will check whether any of them are
|
||||||
|
attached to the PVs concerned and then seek to match those PV tags
|
||||||
|
between existing extents and new extents.
|
||||||
|
.IP
|
||||||
|
The @ prefix for tags is required.
|
||||||
|
Use the special tag "@*" as a wildcard to match any PV tag and so use
|
||||||
|
all PV tags for this purpose.
|
||||||
|
.IP
|
||||||
|
For example, LVs are mirrored between two sites within a single VG.
|
||||||
|
PVs are tagged with either @site1 or @site2 to indicate where
|
||||||
|
they are situated and these two PV tags are selected for use with this
|
||||||
|
allocation policy:
|
||||||
|
.IP
|
||||||
|
cling_tag_list = [ "@site1", "@site2" ]
|
||||||
|
.TP
|
||||||
\fBlog\fP \(em Default log settings
|
\fBlog\fP \(em Default log settings
|
||||||
.IP
|
.IP
|
||||||
\fBfile\fP \(em Location of log file. If this entry is not present, no
|
\fBfile\fP \(em Location of log file. If this entry is not present, no
|
||||||
|
@ -115,7 +115,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
|
|||||||
|
|
||||||
/* Or if VG tags match */
|
/* Or if VG tags match */
|
||||||
if (!process_lv && tags_supplied &&
|
if (!process_lv && tags_supplied &&
|
||||||
str_list_match_list(tags, &vg->tags)) {
|
str_list_match_list(tags, &vg->tags, NULL)) {
|
||||||
process_all = 1;
|
process_all = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
|
|||||||
|
|
||||||
/* LV tag match? */
|
/* LV tag match? */
|
||||||
if (!process_lv && tags_supplied &&
|
if (!process_lv && tags_supplied &&
|
||||||
str_list_match_list(tags, &lvl->lv->tags)) {
|
str_list_match_list(tags, &lvl->lv->tags, NULL)) {
|
||||||
process_lv = 1;
|
process_lv = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +487,7 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
|
|||||||
if (!dm_list_empty(tags) &&
|
if (!dm_list_empty(tags) &&
|
||||||
/* Only process if a tag matches or it's on arg_vgnames */
|
/* Only process if a tag matches or it's on arg_vgnames */
|
||||||
!str_list_match_item(arg_vgnames, vg_name) &&
|
!str_list_match_item(arg_vgnames, vg_name) &&
|
||||||
!str_list_match_list(tags, &cvl_vg->vg->tags))
|
!str_list_match_list(tags, &cvl_vg->vg->tags, NULL))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = process_single_vg(cmd, vg_name, cvl_vg->vg, handle);
|
ret = process_single_vg(cmd, vg_name, cvl_vg->vg, handle);
|
||||||
@ -606,7 +606,7 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
|
|
||||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||||
if (tags && !dm_list_empty(tags) &&
|
if (tags && !dm_list_empty(tags) &&
|
||||||
!str_list_match_list(tags, &pvl->pv->tags)) {
|
!str_list_match_list(tags, &pvl->pv->tags, NULL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((ret = process_single_pv(cmd, vg, pvl->pv, handle)) > ret_max)
|
if ((ret = process_single_pv(cmd, vg, pvl->pv, handle)) > ret_max)
|
||||||
|
Loading…
Reference in New Issue
Block a user