mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-29 00:23:49 +03:00
Compare commits
2 Commits
sourceware
...
dev-lvmguy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d98932039f | ||
|
|
efecf4a1d2 |
@@ -1,8 +1,5 @@
|
|||||||
Version 2.02.169 -
|
Version 2.02.169 -
|
||||||
=====================================
|
=====================================
|
||||||
Reject writemostly/writebehind in lvchange during resynchronization.
|
|
||||||
Deactivate active origin first before removal for improved workflow.
|
|
||||||
Fix regression of accepting options --type and -m with lvresize (2.02.158).
|
|
||||||
Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs.
|
Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs.
|
||||||
Add lvconvert --startpoll, new specific way to start polling conversions.
|
Add lvconvert --startpoll, new specific way to start polling conversions.
|
||||||
Add lvconvert --mergethin, new specific way to merge thin snapshots.
|
Add lvconvert --mergethin, new specific way to merge thin snapshots.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -272,10 +272,18 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -984,6 +992,30 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
|
|||||||
return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL);
|
return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct dev_manager *dm;
|
||||||
|
struct dm_status_raid *status;
|
||||||
|
|
||||||
|
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
|
||||||
|
lv->vg->name, lv->name);
|
||||||
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!(r = dev_manager_raid_status(dm, lv, &status)))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
*data_offset = status->data_offset;
|
||||||
|
|
||||||
|
dev_manager_destroy(dm);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -1013,6 +1045,32 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
|
||||||
|
{
|
||||||
|
struct dev_manager *dm;
|
||||||
|
struct dm_status_raid *status;
|
||||||
|
|
||||||
|
*dev_cnt = 0;
|
||||||
|
|
||||||
|
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_debug_activation("Checking raid device count for LV %s/%s",
|
||||||
|
lv->vg->name, lv->name);
|
||||||
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!dev_manager_raid_status(dm, lv, &status)) {
|
||||||
|
dev_manager_destroy(dm);
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
*dev_cnt = status->dev_count;
|
||||||
|
|
||||||
|
dev_manager_destroy(dm);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
||||||
{
|
{
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|||||||
@@ -168,6 +168,8 @@ int lv_snapshot_percent(const struct logical_volume *lv, dm_percent_t *percent);
|
|||||||
int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv,
|
int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||||
int wait, dm_percent_t *percent, uint32_t *event_nr);
|
int wait, dm_percent_t *percent, uint32_t *event_nr);
|
||||||
int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent);
|
int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent);
|
||||||
|
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt);
|
||||||
|
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset);
|
||||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
|
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
|
||||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
|
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
|
||||||
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
|
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -214,6 +214,14 @@ typedef enum {
|
|||||||
STATUS, /* DM_DEVICE_STATUS ioctl */
|
STATUS, /* DM_DEVICE_STATUS ioctl */
|
||||||
} info_type_t;
|
} info_type_t;
|
||||||
|
|
||||||
|
/* Return length of segment depending on type and reshape_len */
|
||||||
|
static uint32_t _seg_len(const struct lv_segment *seg)
|
||||||
|
{
|
||||||
|
uint32_t reshape_len = seg_is_raid(seg) ? ((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) : 0;
|
||||||
|
|
||||||
|
return seg->len - reshape_len;
|
||||||
|
}
|
||||||
|
|
||||||
static int _info_run(const char *dlid, struct dm_info *dminfo,
|
static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||||
uint32_t *read_ahead,
|
uint32_t *read_ahead,
|
||||||
struct lv_seg_status *seg_status,
|
struct lv_seg_status *seg_status,
|
||||||
@@ -250,7 +258,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
|||||||
if (seg_status && dminfo->exists) {
|
if (seg_status && dminfo->exists) {
|
||||||
start = length = seg_status->seg->lv->vg->extent_size;
|
start = length = seg_status->seg->lv->vg->extent_size;
|
||||||
start *= seg_status->seg->le;
|
start *= seg_status->seg->le;
|
||||||
length *= seg_status->seg->len;
|
length *= _seg_len(seg_status->seg);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
target = dm_get_next_target(dmt, target, &target_start,
|
target = dm_get_next_target(dmt, target, &target_start,
|
||||||
@@ -2214,7 +2222,7 @@ static char *_add_error_or_zero_device(struct dev_manager *dm, struct dm_tree *d
|
|||||||
struct lv_segment *seg_i;
|
struct lv_segment *seg_i;
|
||||||
struct dm_info info;
|
struct dm_info info;
|
||||||
int segno = -1, i = 0;
|
int segno = -1, i = 0;
|
||||||
uint64_t size = (uint64_t) seg->len * seg->lv->vg->extent_size;
|
uint64_t size = (uint64_t) _seg_len(seg) * seg->lv->vg->extent_size;
|
||||||
|
|
||||||
dm_list_iterate_items(seg_i, &seg->lv->segments) {
|
dm_list_iterate_items(seg_i, &seg->lv->segments) {
|
||||||
if (seg == seg_i) {
|
if (seg == seg_i) {
|
||||||
@@ -2500,7 +2508,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
|
|||||||
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
|
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
|
||||||
&dm->target_state, seg,
|
&dm->target_state, seg,
|
||||||
laopts, dnode,
|
laopts, dnode,
|
||||||
extent_size * seg->len,
|
extent_size * _seg_len(seg),
|
||||||
&dm->pvmove_mirror_count);
|
&dm->pvmove_mirror_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2693,7 +2701,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
|||||||
/* Replace target and all its used devs with error mapping */
|
/* Replace target and all its used devs with error mapping */
|
||||||
log_debug_activation("Using error for pending delete %s.",
|
log_debug_activation("Using error for pending delete %s.",
|
||||||
display_lvname(seg->lv));
|
display_lvname(seg->lv));
|
||||||
if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * seg->len))
|
if (!dm_tree_node_add_error_target(dnode, (uint64_t)seg->lv->vg->extent_size * _seg_len(seg)))
|
||||||
return_0;
|
return_0;
|
||||||
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
|
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
|
||||||
return_0;
|
return_0;
|
||||||
@@ -3165,7 +3173,6 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
|||||||
log_error(INTERNAL_ERROR "_tree_action: Action %u not supported.", action);
|
log_error(INTERNAL_ERROR "_tree_action: Action %u not supported.", action);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
* FIXME: Increase these to 64 and further to the MD maximum
|
* FIXME: Increase these to 64 and further to the MD maximum
|
||||||
* once the SubLVs split and name shift got enhanced
|
* once the SubLVs split and name shift got enhanced
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_RAID1_MAX_IMAGES 10
|
#define DEFAULT_RAID1_MAX_IMAGES 64
|
||||||
#define DEFAULT_RAID_MAX_IMAGES 64
|
#define DEFAULT_RAID_MAX_IMAGES 64
|
||||||
#define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */
|
#define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -225,8 +225,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
|||||||
while (le < lvm->lv->le_count) {
|
while (le < lvm->lv->le_count) {
|
||||||
len = _area_length(lvm, le);
|
len = _area_length(lvm, le);
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0,
|
if (!(seg = alloc_lv_segment(segtype, lvm->lv, le, len, 0, 0, 0,
|
||||||
NULL, 1, len, 0, 0, 0, NULL))) {
|
NULL, 1, len, 0, 0, 0, 0, NULL))) {
|
||||||
log_error("Failed to allocate linear segment.");
|
log_error("Failed to allocate linear segment.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -297,10 +297,10 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
|||||||
|
|
||||||
if (!(seg = alloc_lv_segment(segtype, lvm->lv,
|
if (!(seg = alloc_lv_segment(segtype, lvm->lv,
|
||||||
lvm->stripes * first_area_le,
|
lvm->stripes * first_area_le,
|
||||||
lvm->stripes * area_len,
|
lvm->stripes * area_len, 0,
|
||||||
0, lvm->stripe_size, NULL,
|
0, lvm->stripe_size, NULL,
|
||||||
lvm->stripes,
|
lvm->stripes,
|
||||||
area_len, 0, 0, 0, NULL))) {
|
area_len, 0, 0, 0, 0, NULL))) {
|
||||||
log_error("Failed to allocate striped segment.");
|
log_error("Failed to allocate striped segment.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -192,9 +192,9 @@ static int _add_stripe_seg(struct dm_pool *mem,
|
|||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
|
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
|
||||||
area_len * usp->num_devs, 0,
|
area_len * usp->num_devs, 0, 0,
|
||||||
usp->striping, NULL, usp->num_devs,
|
usp->striping, NULL, usp->num_devs,
|
||||||
area_len, 0, 0, 0, NULL))) {
|
area_len, 0, 0, 0, 0, NULL))) {
|
||||||
log_error("Unable to allocate striped lv_segment structure");
|
log_error("Unable to allocate striped lv_segment structure");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -232,8 +232,8 @@ static int _add_linear_seg(struct dm_pool *mem,
|
|||||||
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
|
if (!(seg = alloc_lv_segment(segtype, lv, *le_cur,
|
||||||
area_len, 0, usp->striping,
|
area_len, 0, 0, usp->striping,
|
||||||
NULL, 1, area_len,
|
NULL, 1, area_len, 0,
|
||||||
POOL_PE_SIZE, 0, 0, NULL))) {
|
POOL_PE_SIZE, 0, 0, NULL))) {
|
||||||
log_error("Unable to allocate linear lv_segment "
|
log_error("Unable to allocate linear lv_segment "
|
||||||
"structure");
|
"structure");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -583,8 +583,10 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
|
|||||||
outf(f, "start_extent = %u", seg->le);
|
outf(f, "start_extent = %u", seg->le);
|
||||||
outsize(f, (uint64_t) seg->len * vg->extent_size,
|
outsize(f, (uint64_t) seg->len * vg->extent_size,
|
||||||
"extent_count = %u", seg->len);
|
"extent_count = %u", seg->len);
|
||||||
|
|
||||||
outnl(f);
|
outnl(f);
|
||||||
|
if (seg->reshape_len)
|
||||||
|
outsize(f, (uint64_t) seg->reshape_len * vg->extent_size,
|
||||||
|
"reshape_count = %u", seg->reshape_len);
|
||||||
outf(f, "type = \"%s\"", seg->segtype->name);
|
outf(f, "type = \"%s\"", seg->segtype->name);
|
||||||
|
|
||||||
if (!_out_list(f, &seg->tags, "tags"))
|
if (!_out_list(f, &seg->tags, "tags"))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -61,6 +61,9 @@ static const struct flag _lv_flags[] = {
|
|||||||
{LOCKED, "LOCKED", STATUS_FLAG},
|
{LOCKED, "LOCKED", STATUS_FLAG},
|
||||||
{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
|
{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
|
||||||
{LV_REBUILD, "REBUILD", STATUS_FLAG},
|
{LV_REBUILD, "REBUILD", STATUS_FLAG},
|
||||||
|
{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", STATUS_FLAG},
|
||||||
|
{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", STATUS_FLAG},
|
||||||
|
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", STATUS_FLAG},
|
||||||
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
|
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
|
||||||
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
|
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
|
||||||
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
|
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -354,7 +354,7 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
|||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
const struct dm_config_node *sn_child = sn->child;
|
const struct dm_config_node *sn_child = sn->child;
|
||||||
const struct dm_config_value *cv;
|
const struct dm_config_value *cv;
|
||||||
uint32_t start_extent, extent_count;
|
uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
|
||||||
struct segment_type *segtype;
|
struct segment_type *segtype;
|
||||||
const char *segtype_str;
|
const char *segtype_str;
|
||||||
|
|
||||||
@@ -375,6 +375,12 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_read_int32(sn_child, "reshape_count", &reshape_count))
|
||||||
|
reshape_count = 0;
|
||||||
|
|
||||||
|
if (!_read_int32(sn_child, "data_copies", &data_copies))
|
||||||
|
data_copies = 1;
|
||||||
|
|
||||||
segtype_str = SEG_TYPE_NAME_STRIPED;
|
segtype_str = SEG_TYPE_NAME_STRIPED;
|
||||||
|
|
||||||
if (!dm_config_get_str(sn_child, "type", &segtype_str)) {
|
if (!dm_config_get_str(sn_child, "type", &segtype_str)) {
|
||||||
@@ -389,9 +395,11 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
|||||||
!segtype->ops->text_import_area_count(sn_child, &area_count))
|
!segtype->ops->text_import_area_count(sn_child, &area_count))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
|
area_extents = segtype->parity_devs ?
|
||||||
|
raid_rimage_extents(segtype, extent_count, area_count - segtype->parity_devs, data_copies) : extent_count;
|
||||||
if (!(seg = alloc_lv_segment(segtype, lv, start_extent,
|
if (!(seg = alloc_lv_segment(segtype, lv, start_extent,
|
||||||
extent_count, 0, 0, NULL, area_count,
|
extent_count, reshape_count, 0, 0, NULL, area_count,
|
||||||
extent_count, 0, 0, 0, NULL))) {
|
area_extents, data_copies, 0, 0, 0, NULL))) {
|
||||||
log_error("Segment allocation failed");
|
log_error("Segment allocation failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -1278,6 +1278,8 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
|||||||
repstr[8] = 'm'; /* RAID has 'm'ismatches */
|
repstr[8] = 'm'; /* RAID has 'm'ismatches */
|
||||||
} else if (lv->status & LV_WRITEMOSTLY)
|
} else if (lv->status & LV_WRITEMOSTLY)
|
||||||
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
|
repstr[8] = 'w'; /* sub-LV has 'w'ritemostly */
|
||||||
|
else if (lv->status & LV_REMOVE_AFTER_RESHAPE)
|
||||||
|
repstr[8] = 'R'; /* sub-LV got 'R'emoved from raid set by reshaping */
|
||||||
} else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
|
} else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
|
||||||
if (lvdm->seg_status.cache->fail)
|
if (lvdm->seg_status.cache->fail)
|
||||||
repstr[8] = 'F';
|
repstr[8] = 'F';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -21,11 +21,13 @@
|
|||||||
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
||||||
struct logical_volume *lv,
|
struct logical_volume *lv,
|
||||||
uint32_t le, uint32_t len,
|
uint32_t le, uint32_t len,
|
||||||
|
uint32_t reshape_len,
|
||||||
uint64_t status,
|
uint64_t status,
|
||||||
uint32_t stripe_size,
|
uint32_t stripe_size,
|
||||||
struct logical_volume *log_lv,
|
struct logical_volume *log_lv,
|
||||||
uint32_t area_count,
|
uint32_t area_count,
|
||||||
uint32_t area_len,
|
uint32_t area_len,
|
||||||
|
uint32_t data_copies,
|
||||||
uint32_t chunk_size,
|
uint32_t chunk_size,
|
||||||
uint32_t region_size,
|
uint32_t region_size,
|
||||||
uint32_t extents_copied,
|
uint32_t extents_copied,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -912,11 +912,13 @@ static uint32_t _round_to_stripe_boundary(struct volume_group *vg, uint32_t exte
|
|||||||
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
||||||
struct logical_volume *lv,
|
struct logical_volume *lv,
|
||||||
uint32_t le, uint32_t len,
|
uint32_t le, uint32_t len,
|
||||||
|
uint32_t reshape_len,
|
||||||
uint64_t status,
|
uint64_t status,
|
||||||
uint32_t stripe_size,
|
uint32_t stripe_size,
|
||||||
struct logical_volume *log_lv,
|
struct logical_volume *log_lv,
|
||||||
uint32_t area_count,
|
uint32_t area_count,
|
||||||
uint32_t area_len,
|
uint32_t area_len,
|
||||||
|
uint32_t data_copies,
|
||||||
uint32_t chunk_size,
|
uint32_t chunk_size,
|
||||||
uint32_t region_size,
|
uint32_t region_size,
|
||||||
uint32_t extents_copied,
|
uint32_t extents_copied,
|
||||||
@@ -950,10 +952,12 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
|
|||||||
seg->lv = lv;
|
seg->lv = lv;
|
||||||
seg->le = le;
|
seg->le = le;
|
||||||
seg->len = len;
|
seg->len = len;
|
||||||
|
seg->reshape_len = reshape_len;
|
||||||
seg->status = status;
|
seg->status = status;
|
||||||
seg->stripe_size = stripe_size;
|
seg->stripe_size = stripe_size;
|
||||||
seg->area_count = area_count;
|
seg->area_count = area_count;
|
||||||
seg->area_len = area_len;
|
seg->area_len = area_len;
|
||||||
|
seg->data_copies = data_copies ? : lv_raid_data_copies(segtype, area_count);
|
||||||
seg->chunk_size = chunk_size;
|
seg->chunk_size = chunk_size;
|
||||||
seg->region_size = region_size;
|
seg->region_size = region_size;
|
||||||
seg->extents_copied = extents_copied;
|
seg->extents_copied = extents_copied;
|
||||||
@@ -1047,11 +1051,10 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
|
|||||||
if (lv_is_raid_image(lv)) {
|
if (lv_is_raid_image(lv)) {
|
||||||
/* Calculate the amount of extents to reduce per rmate/rimage LV */
|
/* Calculate the amount of extents to reduce per rmate/rimage LV */
|
||||||
uint32_t rimage_extents;
|
uint32_t rimage_extents;
|
||||||
|
struct lv_segment *seg1 = first_seg(lv);
|
||||||
|
|
||||||
/* FIXME: avoid extra seg_is_*() conditonals */
|
/* FIXME: avoid extra seg_is_*() conditionals here */
|
||||||
area_reduction =_round_to_stripe_boundary(lv->vg, area_reduction,
|
rimage_extents = raid_rimage_extents(seg1->segtype, area_reduction, seg_is_any_raid0(seg) ? 0 : _raid_stripes_count(seg),
|
||||||
(seg_is_raid1(seg) || seg_is_any_raid0(seg)) ? 0 : _raid_stripes_count(seg), 0);
|
|
||||||
rimage_extents = raid_rimage_extents(seg->segtype, area_reduction, seg_is_any_raid0(seg) ? 0 : _raid_stripes_count(seg),
|
|
||||||
seg_is_raid10(seg) ? 1 :_raid_data_copies(seg));
|
seg_is_raid10(seg) ? 1 :_raid_data_copies(seg));
|
||||||
if (!rimage_extents)
|
if (!rimage_extents)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1258,7 +1261,7 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
|
|||||||
* the 'stripes' argument will always need to
|
* the 'stripes' argument will always need to
|
||||||
* be given.
|
* be given.
|
||||||
*/
|
*/
|
||||||
if (!strcmp(segtype->name, _lv_type_names[LV_TYPE_RAID10])) {
|
if (segtype_is_raid10(segtype)) {
|
||||||
if (!stripes)
|
if (!stripes)
|
||||||
return area_count / 2;
|
return area_count / 2;
|
||||||
return stripes;
|
return stripes;
|
||||||
@@ -1278,25 +1281,35 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
|
|||||||
static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
||||||
{
|
{
|
||||||
uint32_t area_reduction, s;
|
uint32_t area_reduction, s;
|
||||||
|
uint32_t areas = (seg->area_count / (seg_is_raid10(seg) ? seg->data_copies : 1)) - seg->segtype->parity_devs;
|
||||||
|
|
||||||
/* Caller must ensure exact divisibility */
|
/* Caller must ensure exact divisibility */
|
||||||
if (seg_is_striped(seg)) {
|
// if (!seg_is_raid10(seg) && (seg_is_striped(seg) || seg_is_striped_raid(seg))) {
|
||||||
if (reduction % seg->area_count) {
|
if (seg_is_striped(seg) || seg_is_striped_raid(seg)) {
|
||||||
|
if (reduction % areas) {
|
||||||
log_error("Segment extent reduction %" PRIu32
|
log_error("Segment extent reduction %" PRIu32
|
||||||
" not divisible by #stripes %" PRIu32,
|
" not divisible by #stripes %" PRIu32,
|
||||||
reduction, seg->area_count);
|
reduction, seg->area_count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
area_reduction = (reduction / seg->area_count);
|
area_reduction = reduction / areas;
|
||||||
} else
|
} else
|
||||||
area_reduction = reduction;
|
area_reduction = reduction;
|
||||||
|
|
||||||
|
//printf("%s[%u] seg->lv=%s seg->len=%u seg->area_len=%u area_reduction=%u\n", __func__, __LINE__, seg->lv ? seg->lv->name : "?", seg->len, seg->area_len, area_reduction);
|
||||||
for (s = 0; s < seg->area_count; s++)
|
for (s = 0; s < seg->area_count; s++)
|
||||||
if (!release_and_discard_lv_segment_area(seg, s, area_reduction))
|
if (!release_and_discard_lv_segment_area(seg, s, area_reduction))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
|
//printf("%s[%u] seg->lv=%s seg->len=%u seg->area_len=%u area_reduction=%u\n", __func__, __LINE__, seg->lv ? seg->lv->name : "?", seg->len, seg->area_len, area_reduction);
|
||||||
seg->len -= reduction;
|
seg->len -= reduction;
|
||||||
seg->area_len -= area_reduction;
|
//pprintf("%s[%u] seg->lv=%s seg->len=%u seg->area_len=%u area_reduction=%u\n", __func__, __LINE__, seg->lv ? seg->lv->name : "?", seg->len, seg->area_len, area_reduction);
|
||||||
|
|
||||||
|
if (seg_is_raid(seg))
|
||||||
|
seg->area_len = seg->len;
|
||||||
|
else
|
||||||
|
seg->area_len -= area_reduction;
|
||||||
|
//printf("%s[%u] seg->lv=%s seg->len=%u seg->area_len=%u area_reduction=%u\n", __func__, __LINE__, seg->lv ? seg->lv->name : "?", seg->len, seg->area_len, area_reduction);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1306,11 +1319,13 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
|||||||
*/
|
*/
|
||||||
static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||||
{
|
{
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg = first_seg(lv);;
|
||||||
uint32_t count = extents;
|
uint32_t count = extents;
|
||||||
uint32_t reduction;
|
uint32_t reduction;
|
||||||
struct logical_volume *pool_lv;
|
struct logical_volume *pool_lv;
|
||||||
struct logical_volume *external_lv = NULL;
|
struct logical_volume *external_lv = NULL;
|
||||||
|
int is_raid10 = seg_is_any_raid10(seg) && seg->reshape_len;
|
||||||
|
uint32_t data_copies = seg->data_copies;
|
||||||
|
|
||||||
if (lv_is_merging_origin(lv)) {
|
if (lv_is_merging_origin(lv)) {
|
||||||
log_debug_metadata("Dropping snapshot merge of %s to removed origin %s.",
|
log_debug_metadata("Dropping snapshot merge of %s to removed origin %s.",
|
||||||
@@ -1318,6 +1333,7 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
|||||||
clear_snapshot_merge(lv);
|
clear_snapshot_merge(lv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("%s[%u] lv=%s is_raid10=%d le_count=%u extents=%u lv->size=%s seg->len=%u seg->area_len=%u seg->reshape_len=%u\n", __func__, __LINE__, lv->name, is_raid10, lv->le_count, extents, display_size(lv->vg->cmd, lv->size), seg ? seg->len : 4711, seg ? seg->area_len : 4711, seg->reshape_len);
|
||||||
dm_list_iterate_back_items(seg, &lv->segments) {
|
dm_list_iterate_back_items(seg, &lv->segments) {
|
||||||
if (!count)
|
if (!count)
|
||||||
break;
|
break;
|
||||||
@@ -1373,11 +1389,21 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
|||||||
count -= reduction;
|
count -= reduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv->le_count -= extents;
|
seg = first_seg(lv);
|
||||||
|
//printf("%s[%u] lv=%s le_count=%u extents=%u lv->size=%s seg->len=%u seg->area_len=%u\n", __func__, __LINE__, lv->name, lv->le_count, extents, display_size(lv->vg->cmd, lv->size), seg ? seg->len : 4711, seg ? seg->area_len : 4711);
|
||||||
|
if (is_raid10) {
|
||||||
|
lv->le_count -= extents * data_copies;
|
||||||
|
if (seg)
|
||||||
|
seg->len = seg->area_len = lv->le_count;
|
||||||
|
} else
|
||||||
|
lv->le_count -= extents;
|
||||||
|
|
||||||
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
|
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
|
||||||
|
//printf("%s[%u] lv=%s le_count=%u lv->size=%s seg->len=%u seg->area_len=%u\n", __func__, __LINE__, lv->name, lv->le_count, display_size(lv->vg->cmd, lv->size), seg ? seg->len : 4711, seg ? seg->area_len : 4711);
|
||||||
|
|
||||||
if (!delete)
|
if (!delete)
|
||||||
return 1;
|
return 1;
|
||||||
|
//printf("%s[%u] lv=%s le_count=%u lv->size=%s seg->len=%u seg->area_len=%u\n", __func__, __LINE__, lv->name, lv->le_count, display_size(lv->vg->cmd, lv->size), seg ? seg->len : 4711, seg ? seg->area_len : 4711);
|
||||||
|
|
||||||
if (lv == lv->vg->pool_metadata_spare_lv) {
|
if (lv == lv->vg->pool_metadata_spare_lv) {
|
||||||
lv->status &= ~POOL_METADATA_SPARE;
|
lv->status &= ~POOL_METADATA_SPARE;
|
||||||
@@ -1793,10 +1819,10 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
|
|||||||
area_multiple = _calc_area_multiple(segtype, area_count, 0);
|
area_multiple = _calc_area_multiple(segtype, area_count, 0);
|
||||||
extents = aa[0].len * area_multiple;
|
extents = aa[0].len * area_multiple;
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents,
|
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, 0,
|
||||||
status, stripe_size, NULL,
|
status, stripe_size, NULL,
|
||||||
area_count,
|
area_count,
|
||||||
aa[0].len, 0u, region_size, 0u, NULL))) {
|
aa[0].len, 0, 0u, region_size, 0u, NULL))) {
|
||||||
log_error("Couldn't allocate new LV segment.");
|
log_error("Couldn't allocate new LV segment.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1808,7 +1834,7 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
|
|||||||
dm_list_add(&lv->segments, &seg->list);
|
dm_list_add(&lv->segments, &seg->list);
|
||||||
|
|
||||||
extents = aa[0].len * area_multiple;
|
extents = aa[0].len * area_multiple;
|
||||||
|
//printf("%s[%u] le_count=%u extents=%u\n", __func__, __LINE__, lv->le_count, extents);
|
||||||
if (!_setup_lv_size(lv, lv->le_count + extents))
|
if (!_setup_lv_size(lv, lv->le_count + extents))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -3234,9 +3260,9 @@ int lv_add_virtual_segment(struct logical_volume *lv, uint64_t status,
|
|||||||
seg->area_len += extents;
|
seg->area_len += extents;
|
||||||
seg->len += extents;
|
seg->len += extents;
|
||||||
} else {
|
} else {
|
||||||
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents,
|
if (!(seg = alloc_lv_segment(segtype, lv, lv->le_count, extents, 0,
|
||||||
status, 0, NULL, 0,
|
status, 0, NULL, 0,
|
||||||
extents, 0, 0, 0, NULL))) {
|
extents, 0, 0, 0, 0, NULL))) {
|
||||||
log_error("Couldn't allocate new %s segment.", segtype->name);
|
log_error("Couldn't allocate new %s segment.", segtype->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3562,10 +3588,10 @@ static struct lv_segment *_convert_seg_to_mirror(struct lv_segment *seg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(newseg = alloc_lv_segment(get_segtype_from_string(seg->lv->vg->cmd, SEG_TYPE_NAME_MIRROR),
|
if (!(newseg = alloc_lv_segment(get_segtype_from_string(seg->lv->vg->cmd, SEG_TYPE_NAME_MIRROR),
|
||||||
seg->lv, seg->le, seg->len,
|
seg->lv, seg->le, seg->len, 0,
|
||||||
seg->status, seg->stripe_size,
|
seg->status, seg->stripe_size,
|
||||||
log_lv,
|
log_lv,
|
||||||
seg->area_count, seg->area_len,
|
seg->area_count, seg->area_len, 0,
|
||||||
seg->chunk_size, region_size,
|
seg->chunk_size, region_size,
|
||||||
seg->extents_copied, NULL))) {
|
seg->extents_copied, NULL))) {
|
||||||
log_error("Couldn't allocate converted LV segment.");
|
log_error("Couldn't allocate converted LV segment.");
|
||||||
@@ -3667,8 +3693,8 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_seg = alloc_lv_segment(segtype, copy_lv,
|
if (!(new_seg = alloc_lv_segment(segtype, copy_lv,
|
||||||
seg->le, seg->len, PVMOVE, 0,
|
seg->le, seg->len, 0, PVMOVE, 0,
|
||||||
NULL, 1, seg->len,
|
NULL, 1, seg->len, 0,
|
||||||
0, 0, 0, NULL)))
|
0, 0, 0, NULL)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -3863,9 +3889,9 @@ static int _lv_insert_empty_sublvs(struct logical_volume *lv,
|
|||||||
/*
|
/*
|
||||||
* First, create our top-level segment for our top-level LV
|
* First, create our top-level segment for our top-level LV
|
||||||
*/
|
*/
|
||||||
if (!(mapseg = alloc_lv_segment(segtype, lv, 0, 0, lv->status,
|
if (!(mapseg = alloc_lv_segment(segtype, lv, 0, 0, 0, lv->status,
|
||||||
stripe_size, NULL,
|
stripe_size, NULL,
|
||||||
devices, 0, 0, region_size, 0, NULL))) {
|
devices, 0, 0, 0, region_size, 0, NULL))) {
|
||||||
log_error("Failed to create mapping segment for %s.",
|
log_error("Failed to create mapping segment for %s.",
|
||||||
display_lvname(lv));
|
display_lvname(lv));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4063,9 +4089,13 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
|||||||
lv_set_hidden(seg_metalv(seg, s));
|
lv_set_hidden(seg_metalv(seg, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->area_len += extents / area_multiple;
|
|
||||||
seg->len += extents;
|
seg->len += extents;
|
||||||
|
if (seg_is_raid(seg))
|
||||||
|
seg->area_len = seg->len;
|
||||||
|
else
|
||||||
|
seg->area_len += extents / area_multiple;
|
||||||
|
|
||||||
|
//pprintf("%s[%u] le_count=%u extents=%u seg->len=%u seg-area_len=%u\n", __func__, __LINE__, lv->le_count, extents, seg->len, seg->area_len);
|
||||||
if (!_setup_lv_size(lv, lv->le_count + extents))
|
if (!_setup_lv_size(lv, lv->le_count + extents))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -6229,21 +6259,12 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
|
|||||||
/* Remove snapshot LVs first */
|
/* Remove snapshot LVs first */
|
||||||
if ((force == PROMPT) &&
|
if ((force == PROMPT) &&
|
||||||
/* Active snapshot already needs to confirm each active LV */
|
/* Active snapshot already needs to confirm each active LV */
|
||||||
(yes_no_prompt("Do you really want to remove%s "
|
!lv_is_active(lv) &&
|
||||||
"%sorigin logical volume %s with %u snapshot(s)? [y/n]: ",
|
yes_no_prompt("Removing origin %s will also remove %u "
|
||||||
lv_is_active(lv) ? " active" : "",
|
"snapshots(s). Proceed? [y/n]: ",
|
||||||
vg_is_clustered(lv->vg) ? "clustered " : "",
|
lv->name, lv->origin_count) == 'n')
|
||||||
display_lvname(lv),
|
|
||||||
lv->origin_count) == 'n'))
|
|
||||||
goto no_remove;
|
goto no_remove;
|
||||||
|
|
||||||
if (!deactivate_lv(cmd, lv)) {
|
|
||||||
stack;
|
|
||||||
goto no_remove;
|
|
||||||
}
|
|
||||||
log_verbose("Removing origin logical volume %s with %u snapshots(s).",
|
|
||||||
display_lvname(lv), lv->origin_count);
|
|
||||||
|
|
||||||
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||||
if (!lv_remove_with_dependencies(cmd, dm_list_struct_base(snh, struct lv_segment,
|
if (!lv_remove_with_dependencies(cmd, dm_list_struct_base(snh, struct lv_segment,
|
||||||
origin_list)->cow,
|
origin_list)->cow,
|
||||||
@@ -6309,7 +6330,6 @@ static int _lv_update_and_reload(struct logical_volume *lv, int origin_only)
|
|||||||
|
|
||||||
log_very_verbose("Updating logical volume %s on disk(s)%s.",
|
log_very_verbose("Updating logical volume %s on disk(s)%s.",
|
||||||
display_lvname(lock_lv), origin_only ? " (origin only)": "");
|
display_lvname(lock_lv), origin_only ? " (origin only)": "");
|
||||||
|
|
||||||
if (!vg_write(vg))
|
if (!vg_write(vg))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -6776,8 +6796,8 @@ struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
|
|||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
/* allocate a new linear segment */
|
/* allocate a new linear segment */
|
||||||
if (!(mapseg = alloc_lv_segment(segtype, lv_where, 0, layer_lv->le_count,
|
if (!(mapseg = alloc_lv_segment(segtype, lv_where, 0, layer_lv->le_count, 0,
|
||||||
status, 0, NULL, 1, layer_lv->le_count,
|
status, 0, NULL, 1, layer_lv->le_count, 0,
|
||||||
0, 0, 0, NULL)))
|
0, 0, 0, NULL)))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
@@ -6833,8 +6853,8 @@ static int _extend_layer_lv_for_segment(struct logical_volume *layer_lv,
|
|||||||
|
|
||||||
/* allocate a new segment */
|
/* allocate a new segment */
|
||||||
if (!(mapseg = alloc_lv_segment(segtype, layer_lv, layer_lv->le_count,
|
if (!(mapseg = alloc_lv_segment(segtype, layer_lv, layer_lv->le_count,
|
||||||
seg->area_len, status, 0,
|
seg->area_len, 0, status, 0,
|
||||||
NULL, 1, seg->area_len, 0, 0, 0, seg)))
|
NULL, 1, seg->area_len, 0, 0, 0, 0, seg)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
/* map the new segment to the original underlying are */
|
/* map the new segment to the original underlying are */
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ static void _check_raid_seg(struct lv_segment *seg, int *error_count)
|
|||||||
if (!seg->areas)
|
if (!seg->areas)
|
||||||
raid_seg_error("zero areas");
|
raid_seg_error("zero areas");
|
||||||
|
|
||||||
if (seg->extents_copied > seg->area_len)
|
if (seg->extents_copied > seg->len)
|
||||||
raid_seg_error_val("extents_copied too large", seg->extents_copied);
|
raid_seg_error_val("extents_copied too large", seg->extents_copied);
|
||||||
|
|
||||||
/* Default < 10, change once raid1 split shift and rename SubLVs works! */
|
/* Default < 10, change once raid1 split shift and rename SubLVs works! */
|
||||||
@@ -475,7 +475,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
|||||||
struct lv_segment *seg, *seg2;
|
struct lv_segment *seg, *seg2;
|
||||||
uint32_t le = 0;
|
uint32_t le = 0;
|
||||||
unsigned seg_count = 0, seg_found, external_lv_found = 0;
|
unsigned seg_count = 0, seg_found, external_lv_found = 0;
|
||||||
uint32_t area_multiplier, s;
|
uint32_t data_rimage_count, s;
|
||||||
struct seg_list *sl;
|
struct seg_list *sl;
|
||||||
struct glv_list *glvl;
|
struct glv_list *glvl;
|
||||||
int error_count = 0;
|
int error_count = 0;
|
||||||
@@ -498,13 +498,14 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
|||||||
inc_error_count;
|
inc_error_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
area_multiplier = segtype_is_striped(seg->segtype) ?
|
|
||||||
seg->area_count : 1;
|
|
||||||
|
|
||||||
if (seg->area_len * area_multiplier != seg->len) {
|
data_rimage_count = seg->area_count - seg->segtype->parity_devs;
|
||||||
log_error("LV %s: segment %u has inconsistent "
|
/* FIXME: raid varies seg->area_len? */
|
||||||
"area_len %u",
|
if (seg->len != seg->area_len &&
|
||||||
lv->name, seg_count, seg->area_len);
|
seg->len != seg->area_len * data_rimage_count) {
|
||||||
|
log_error("LV %s: segment %u with len=%u "
|
||||||
|
" has inconsistent area_len %u",
|
||||||
|
lv->name, seg_count, seg->len, seg->area_len);
|
||||||
inc_error_count;
|
inc_error_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,10 +767,10 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
|||||||
|
|
||||||
/* Clone the existing segment */
|
/* Clone the existing segment */
|
||||||
if (!(split_seg = alloc_lv_segment(seg->segtype,
|
if (!(split_seg = alloc_lv_segment(seg->segtype,
|
||||||
seg->lv, seg->le, seg->len,
|
seg->lv, seg->le, seg->len, seg->reshape_len,
|
||||||
seg->status, seg->stripe_size,
|
seg->status, seg->stripe_size,
|
||||||
seg->log_lv,
|
seg->log_lv,
|
||||||
seg->area_count, seg->area_len,
|
seg->area_count, seg->area_len, seg->data_copies,
|
||||||
seg->chunk_size, seg->region_size,
|
seg->chunk_size, seg->region_size,
|
||||||
seg->extents_copied, seg->pvmove_source_seg))) {
|
seg->extents_copied, seg->pvmove_source_seg))) {
|
||||||
log_error("Couldn't allocate cloned LV segment.");
|
log_error("Couldn't allocate cloned LV segment.");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -137,7 +137,11 @@
|
|||||||
e.g. to prohibit allocation of a RAID image
|
e.g. to prohibit allocation of a RAID image
|
||||||
on a PV already holing an image of the RAID set */
|
on a PV already holing an image of the RAID set */
|
||||||
#define LOCKD_SANLOCK_LV UINT64_C(0x0080000000000000) /* LV - Internal use only */
|
#define LOCKD_SANLOCK_LV UINT64_C(0x0080000000000000) /* LV - Internal use only */
|
||||||
/* Next unused flag: UINT64_C(0x0100000000000000) */
|
#define LV_RESHAPE_DELTA_DISKS_PLUS UINT64_C(0x0100000000000000) /* LV reshape flag delta disks plus image(s) */
|
||||||
|
#define LV_RESHAPE_DELTA_DISKS_MINUS UINT64_C(0x0200000000000000) /* LV reshape flag delta disks minus image(s) */
|
||||||
|
|
||||||
|
#define LV_REMOVE_AFTER_RESHAPE UINT64_C(0x0400000000000000) /* LV needs to be removed after a shrinking reshape */
|
||||||
|
/* Next unused flag: UINT64_C(0x0800000000000000) */
|
||||||
|
|
||||||
/* Format features flags */
|
/* Format features flags */
|
||||||
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
|
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
|
||||||
@@ -446,6 +450,7 @@ struct lv_segment {
|
|||||||
const struct segment_type *segtype;
|
const struct segment_type *segtype;
|
||||||
uint32_t le;
|
uint32_t le;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
uint32_t reshape_len; /* For RAID: user hidden additional out of place reshaping length off area_len and len */
|
||||||
|
|
||||||
uint64_t status;
|
uint64_t status;
|
||||||
|
|
||||||
@@ -454,6 +459,7 @@ struct lv_segment {
|
|||||||
uint32_t writebehind; /* For RAID (RAID1 only) */
|
uint32_t writebehind; /* For RAID (RAID1 only) */
|
||||||
uint32_t min_recovery_rate; /* For RAID */
|
uint32_t min_recovery_rate; /* For RAID */
|
||||||
uint32_t max_recovery_rate; /* For RAID */
|
uint32_t max_recovery_rate; /* For RAID */
|
||||||
|
uint32_t data_offset; /* For RAID: data offset in sectors on each data component image */
|
||||||
uint32_t area_count;
|
uint32_t area_count;
|
||||||
uint32_t area_len;
|
uint32_t area_len;
|
||||||
uint32_t chunk_size; /* For snapshots/thin_pool. In sectors. */
|
uint32_t chunk_size; /* For snapshots/thin_pool. In sectors. */
|
||||||
@@ -464,6 +470,7 @@ struct lv_segment {
|
|||||||
struct logical_volume *cow;
|
struct logical_volume *cow;
|
||||||
struct dm_list origin_list;
|
struct dm_list origin_list;
|
||||||
uint32_t region_size; /* For mirrors, replicators - in sectors */
|
uint32_t region_size; /* For mirrors, replicators - in sectors */
|
||||||
|
uint32_t data_copies; /* For RAID: number of data copies (e.g. 3 for RAID 6 */
|
||||||
uint32_t extents_copied;/* Number of extents synced for raids/mirrors */
|
uint32_t extents_copied;/* Number of extents synced for raids/mirrors */
|
||||||
struct logical_volume *log_lv;
|
struct logical_volume *log_lv;
|
||||||
struct lv_segment *pvmove_source_seg;
|
struct lv_segment *pvmove_source_seg;
|
||||||
@@ -1205,7 +1212,8 @@ struct logical_volume *first_replicator_dev(const struct logical_volume *lv);
|
|||||||
int lv_is_raid_with_tracking(const struct logical_volume *lv);
|
int lv_is_raid_with_tracking(const struct logical_volume *lv);
|
||||||
uint32_t lv_raid_image_count(const struct logical_volume *lv);
|
uint32_t lv_raid_image_count(const struct logical_volume *lv);
|
||||||
int lv_raid_change_image_count(struct logical_volume *lv,
|
int lv_raid_change_image_count(struct logical_volume *lv,
|
||||||
uint32_t new_count, struct dm_list *allocate_pvs);
|
uint32_t new_count, const uint32_t region_size,
|
||||||
|
struct dm_list *allocate_pvs);
|
||||||
int lv_raid_split(struct logical_volume *lv, const char *split_name,
|
int lv_raid_split(struct logical_volume *lv, const char *split_name,
|
||||||
uint32_t new_count, struct dm_list *splittable_pvs);
|
uint32_t new_count, struct dm_list *splittable_pvs);
|
||||||
int lv_raid_split_and_track(struct logical_volume *lv,
|
int lv_raid_split_and_track(struct logical_volume *lv,
|
||||||
@@ -1232,6 +1240,7 @@ uint32_t raid_rimage_extents(const struct segment_type *segtype,
|
|||||||
uint32_t raid_ensure_min_region_size(const struct logical_volume *lv, uint64_t raid_size, uint32_t region_size);
|
uint32_t raid_ensure_min_region_size(const struct logical_volume *lv, uint64_t raid_size, uint32_t region_size);
|
||||||
int lv_raid_change_region_size(struct logical_volume *lv,
|
int lv_raid_change_region_size(struct logical_volume *lv,
|
||||||
int yes, int force, uint32_t new_region_size);
|
int yes, int force, uint32_t new_region_size);
|
||||||
|
uint32_t lv_raid_data_copies(const struct segment_type *segtype, uint32_t area_count);
|
||||||
int lv_raid_in_sync(const struct logical_volume *lv);
|
int lv_raid_in_sync(const struct logical_volume *lv);
|
||||||
/* -- metadata/raid_manip.c */
|
/* -- metadata/raid_manip.c */
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,8 @@ struct segment_type *get_segtype_from_flag(struct cmd_context *cmd, uint64_t fla
|
|||||||
{
|
{
|
||||||
struct segment_type *segtype;
|
struct segment_type *segtype;
|
||||||
|
|
||||||
dm_list_iterate_items(segtype, &cmd->segtypes)
|
/* Iterate backwards to provide aliases; e.g. raid5 instead of raid5_ls */
|
||||||
|
dm_list_iterate_back_items(segtype, &cmd->segtypes)
|
||||||
if (flag & segtype->flags)
|
if (flag & segtype->flags)
|
||||||
return segtype;
|
return segtype;
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,11 @@ struct dev_manager;
|
|||||||
#define segtype_is_any_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
|
#define segtype_is_any_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
|
||||||
#define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
|
#define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
|
||||||
#define segtype_is_raid10_near(segtype) segtype_is_raid10(segtype)
|
#define segtype_is_raid10_near(segtype) segtype_is_raid10(segtype)
|
||||||
|
/* FIXME: once raid10_offset supported */
|
||||||
|
#define segtype_is_raid10_offset(segtype) 0 // ((segtype)->flags & SEG_RAID10_OFFSET ? 1 : 0)
|
||||||
#define segtype_is_raid_with_meta(segtype) (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
|
#define segtype_is_raid_with_meta(segtype) (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
|
||||||
|
#define segtype_is_striped_raid(segtype) (segtype_is_raid(segtype) && !segtype_is_raid1(segtype))
|
||||||
|
#define segtype_is_reshapable_raid(segtype) ((segtype_is_striped_raid(segtype) && !segtype_is_any_raid0(segtype)) || segtype_is_raid10_near(segtype) || segtype_is_raid10_offset(segtype))
|
||||||
#define segtype_is_snapshot(segtype) ((segtype)->flags & SEG_SNAPSHOT ? 1 : 0)
|
#define segtype_is_snapshot(segtype) ((segtype)->flags & SEG_SNAPSHOT ? 1 : 0)
|
||||||
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
|
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
|
||||||
#define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0)
|
#define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0)
|
||||||
@@ -190,6 +194,8 @@ struct dev_manager;
|
|||||||
#define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype)
|
#define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype)
|
||||||
#define seg_is_raid10_near(seg) segtype_is_raid10_near((seg)->segtype)
|
#define seg_is_raid10_near(seg) segtype_is_raid10_near((seg)->segtype)
|
||||||
#define seg_is_raid_with_meta(seg) segtype_is_raid_with_meta((seg)->segtype)
|
#define seg_is_raid_with_meta(seg) segtype_is_raid_with_meta((seg)->segtype)
|
||||||
|
#define seg_is_striped_raid(seg) segtype_is_striped_raid((seg)->segtype)
|
||||||
|
#define seg_is_reshapable_raid(seg) segtype_is_reshapable_raid((seg)->segtype)
|
||||||
#define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0)
|
#define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0)
|
||||||
#define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)
|
#define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)
|
||||||
#define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype)
|
#define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype)
|
||||||
@@ -280,6 +286,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
|
|||||||
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
|
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
|
||||||
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
|
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
|
||||||
#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */
|
#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */
|
||||||
|
#define RAID_FEATURE_RESHAPE (1U << 4) /* version 1.10.2 */
|
||||||
|
|
||||||
#ifdef RAID_INTERNAL
|
#ifdef RAID_INTERNAL
|
||||||
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
|
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
|
||||||
|
|||||||
@@ -238,8 +238,8 @@ static struct lv_segment *_alloc_snapshot_seg(struct logical_volume *lv)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(segtype, lv, 0, lv->le_count, 0, 0,
|
if (!(seg = alloc_lv_segment(segtype, lv, 0, lv->le_count, 0, 0, 0,
|
||||||
NULL, 0, lv->le_count, 0, 0, 0, NULL))) {
|
NULL, 0, lv->le_count, 0, 0, 0, 0, NULL))) {
|
||||||
log_error("Couldn't allocate new snapshot segment.");
|
log_error("Couldn't allocate new snapshot segment.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
126
lib/raid/raid.c
126
lib/raid/raid.c
@@ -137,6 +137,7 @@ static int _raid_text_import(struct lv_segment *seg,
|
|||||||
} raid_attr_import[] = {
|
} raid_attr_import[] = {
|
||||||
{ "region_size", &seg->region_size },
|
{ "region_size", &seg->region_size },
|
||||||
{ "stripe_size", &seg->stripe_size },
|
{ "stripe_size", &seg->stripe_size },
|
||||||
|
{ "data_copies", &seg->data_copies },
|
||||||
{ "writebehind", &seg->writebehind },
|
{ "writebehind", &seg->writebehind },
|
||||||
{ "min_recovery_rate", &seg->min_recovery_rate },
|
{ "min_recovery_rate", &seg->min_recovery_rate },
|
||||||
{ "max_recovery_rate", &seg->max_recovery_rate },
|
{ "max_recovery_rate", &seg->max_recovery_rate },
|
||||||
@@ -146,6 +147,10 @@ static int _raid_text_import(struct lv_segment *seg,
|
|||||||
for (i = 0; i < DM_ARRAY_SIZE(raid_attr_import); i++, aip++) {
|
for (i = 0; i < DM_ARRAY_SIZE(raid_attr_import); i++, aip++) {
|
||||||
if (dm_config_has_node(sn, aip->name)) {
|
if (dm_config_has_node(sn, aip->name)) {
|
||||||
if (!dm_config_get_uint32(sn, aip->name, aip->var)) {
|
if (!dm_config_get_uint32(sn, aip->name, aip->var)) {
|
||||||
|
if (!strcmp(aip->name, "data_copies")) {
|
||||||
|
*aip->var = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
log_error("Couldn't read '%s' for segment %s of logical volume %s.",
|
log_error("Couldn't read '%s' for segment %s of logical volume %s.",
|
||||||
aip->name, dm_config_parent_name(sn), seg->lv->name);
|
aip->name, dm_config_parent_name(sn), seg->lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -165,6 +170,9 @@ static int _raid_text_import(struct lv_segment *seg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (seg->data_copies < 2)
|
||||||
|
seg->data_copies = lv_raid_data_copies(seg->segtype, seg->area_count);
|
||||||
|
|
||||||
if (seg_is_any_raid0(seg))
|
if (seg_is_any_raid0(seg))
|
||||||
seg->area_len /= seg->area_count;
|
seg->area_len /= seg->area_count;
|
||||||
|
|
||||||
@@ -183,18 +191,31 @@ static int _raid_text_export_raid0(const struct lv_segment *seg, struct formatte
|
|||||||
|
|
||||||
static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f)
|
static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f)
|
||||||
{
|
{
|
||||||
outf(f, "device_count = %u", seg->area_count);
|
int raid0 = seg_is_any_raid0(seg);
|
||||||
|
|
||||||
|
if (raid0)
|
||||||
|
outfc(f, (seg->area_count == 1) ? "# linear" : NULL,
|
||||||
|
"stripe_count = %u", seg->area_count);
|
||||||
|
|
||||||
|
else {
|
||||||
|
outf(f, "device_count = %u", seg->area_count);
|
||||||
|
if (seg_is_any_raid10(seg) && seg->data_copies > 0)
|
||||||
|
outf(f, "data_copies = %" PRIu32, seg->data_copies);
|
||||||
|
if (seg->region_size)
|
||||||
|
outf(f, "region_size = %" PRIu32, seg->region_size);
|
||||||
|
}
|
||||||
|
|
||||||
if (seg->stripe_size)
|
if (seg->stripe_size)
|
||||||
outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
|
outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
|
||||||
if (seg->region_size)
|
|
||||||
outf(f, "region_size = %" PRIu32, seg->region_size);
|
if (!raid0) {
|
||||||
if (seg->writebehind)
|
if (seg_is_raid1(seg) && seg->writebehind)
|
||||||
outf(f, "writebehind = %" PRIu32, seg->writebehind);
|
outf(f, "writebehind = %" PRIu32, seg->writebehind);
|
||||||
if (seg->min_recovery_rate)
|
if (seg->min_recovery_rate)
|
||||||
outf(f, "min_recovery_rate = %" PRIu32, seg->min_recovery_rate);
|
outf(f, "min_recovery_rate = %" PRIu32, seg->min_recovery_rate);
|
||||||
if (seg->max_recovery_rate)
|
if (seg->max_recovery_rate)
|
||||||
outf(f, "max_recovery_rate = %" PRIu32, seg->max_recovery_rate);
|
outf(f, "max_recovery_rate = %" PRIu32, seg->max_recovery_rate);
|
||||||
|
}
|
||||||
|
|
||||||
return out_areas(f, seg, "raid");
|
return out_areas(f, seg, "raid");
|
||||||
}
|
}
|
||||||
@@ -216,14 +237,16 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
|
|||||||
struct dm_tree_node *node, uint64_t len,
|
struct dm_tree_node *node, uint64_t len,
|
||||||
uint32_t *pvmove_mirror_count __attribute__((unused)))
|
uint32_t *pvmove_mirror_count __attribute__((unused)))
|
||||||
{
|
{
|
||||||
|
int delta_disks = 0, delta_disks_minus = 0, delta_disks_plus = 0, data_offset = 0;
|
||||||
uint32_t s;
|
uint32_t s;
|
||||||
uint64_t flags = 0;
|
uint64_t flags = 0;
|
||||||
uint64_t rebuilds = 0;
|
uint64_t rebuilds[4];
|
||||||
uint64_t writemostly = 0;
|
uint64_t writemostly[4];
|
||||||
struct dm_tree_node_raid_params params;
|
struct dm_tree_node_raid_params params;
|
||||||
int raid0 = seg_is_any_raid0(seg);
|
|
||||||
|
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
memset(&rebuilds, 0, sizeof(rebuilds));
|
||||||
|
memset(&writemostly, 0, sizeof(writemostly));
|
||||||
|
|
||||||
if (!seg->area_count) {
|
if (!seg->area_count) {
|
||||||
log_error(INTERNAL_ERROR "_raid_add_target_line called "
|
log_error(INTERNAL_ERROR "_raid_add_target_line called "
|
||||||
@@ -232,63 +255,84 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 64 device restriction imposed by kernel as well. It is
|
* 253 device restriction imposed by kernel due to MD and dm-raid bitfield limitation in superblock.
|
||||||
* not strictly a userspace limitation.
|
* It is not strictly a userspace limitation.
|
||||||
*/
|
*/
|
||||||
if (seg->area_count > 64) {
|
if (seg->area_count > DEFAULT_RAID_MAX_IMAGES) {
|
||||||
log_error("Unable to handle more than 64 devices in a "
|
log_error("Unable to handle more than %u devices in a "
|
||||||
"single RAID array");
|
"single RAID array", DEFAULT_RAID_MAX_IMAGES);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!raid0) {
|
if (!seg_is_any_raid0(seg)) {
|
||||||
if (!seg->region_size) {
|
if (!seg->region_size) {
|
||||||
log_error("Missing region size for mirror segment.");
|
log_error("Missing region size for raid segment in %s.",
|
||||||
|
seg_lv(seg, 0)->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s = 0; s < seg->area_count; s++)
|
for (s = 0; s < seg->area_count; s++) {
|
||||||
if (seg_lv(seg, s)->status & LV_REBUILD)
|
uint64_t status = seg_lv(seg, s)->status;
|
||||||
rebuilds |= 1ULL << s;
|
|
||||||
|
|
||||||
for (s = 0; s < seg->area_count; s++)
|
if (status & LV_REBUILD)
|
||||||
if (seg_lv(seg, s)->status & LV_WRITEMOSTLY)
|
rebuilds[s/64] |= 1ULL << (s%64);
|
||||||
writemostly |= 1ULL << s;
|
|
||||||
|
if (status & LV_RESHAPE_DELTA_DISKS_PLUS) {
|
||||||
|
delta_disks++;
|
||||||
|
delta_disks_plus++;
|
||||||
|
} else if (status & LV_RESHAPE_DELTA_DISKS_MINUS) {
|
||||||
|
delta_disks--;
|
||||||
|
delta_disks_minus++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta_disks_plus && delta_disks_minus) {
|
||||||
|
log_error(INTERNAL_ERROR "Invalid request for delta disks minus and delta disks plus!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & LV_WRITEMOSTLY)
|
||||||
|
writemostly[s/64] |= 1ULL << (s%64);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_offset = seg->data_offset;
|
||||||
|
|
||||||
if (mirror_in_sync())
|
if (mirror_in_sync())
|
||||||
flags = DM_NOSYNC;
|
flags = DM_NOSYNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
params.raid_type = lvseg_name(seg);
|
params.raid_type = lvseg_name(seg);
|
||||||
params.stripe_size = seg->stripe_size;
|
|
||||||
params.flags = flags;
|
|
||||||
|
|
||||||
if (raid0) {
|
if (seg->segtype->parity_devs) {
|
||||||
params.mirrors = 1;
|
|
||||||
params.stripes = seg->area_count;
|
|
||||||
} else if (seg->segtype->parity_devs) {
|
|
||||||
/* RAID 4/5/6 */
|
/* RAID 4/5/6 */
|
||||||
params.mirrors = 1;
|
params.mirrors = 1;
|
||||||
params.stripes = seg->area_count - seg->segtype->parity_devs;
|
params.stripes = seg->area_count - seg->segtype->parity_devs;
|
||||||
} else if (seg_is_raid10(seg)) {
|
} else if (seg_is_any_raid0(seg)) {
|
||||||
/* RAID 10 only supports 2 mirrors now */
|
params.mirrors = 1;
|
||||||
params.mirrors = 2;
|
params.stripes = seg->area_count;
|
||||||
params.stripes = seg->area_count / 2;
|
} else if (seg_is_any_raid10(seg)) {
|
||||||
|
params.data_copies = seg->data_copies;
|
||||||
|
params.stripes = seg->area_count;
|
||||||
} else {
|
} else {
|
||||||
/* RAID 1 */
|
/* RAID 1 */
|
||||||
params.mirrors = seg->area_count;
|
params.mirrors = seg->data_copies;
|
||||||
params.stripes = 1;
|
params.stripes = 1;
|
||||||
params.writebehind = seg->writebehind;
|
params.writebehind = seg->writebehind;
|
||||||
|
memcpy(params.writemostly, writemostly, sizeof(params.writemostly));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!raid0) {
|
/* RAID 0 doesn't have a bitmap, thus no region_size, rebuilds etc. */
|
||||||
|
if (!seg_is_any_raid0(seg)) {
|
||||||
params.region_size = seg->region_size;
|
params.region_size = seg->region_size;
|
||||||
params.rebuilds = rebuilds;
|
memcpy(params.rebuilds, rebuilds, sizeof(params.rebuilds));
|
||||||
params.writemostly = writemostly;
|
|
||||||
params.min_recovery_rate = seg->min_recovery_rate;
|
params.min_recovery_rate = seg->min_recovery_rate;
|
||||||
params.max_recovery_rate = seg->max_recovery_rate;
|
params.max_recovery_rate = seg->max_recovery_rate;
|
||||||
|
params.delta_disks = delta_disks;
|
||||||
|
params.data_offset = data_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
params.stripe_size = seg->stripe_size;
|
||||||
|
params.flags = flags;
|
||||||
|
|
||||||
if (!dm_tree_node_add_raid_target_with_params(node, len, ¶ms))
|
if (!dm_tree_node_add_raid_target_with_params(node, len, ¶ms))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -450,6 +494,10 @@ static int _raid_target_present(struct cmd_context *cmd,
|
|||||||
else
|
else
|
||||||
log_very_verbose("Target raid does not support %s.",
|
log_very_verbose("Target raid does not support %s.",
|
||||||
SEG_TYPE_NAME_RAID4);
|
SEG_TYPE_NAME_RAID4);
|
||||||
|
|
||||||
|
if (maj > 1 ||
|
||||||
|
(maj == 1 && (min > 10 || (min == 10 && patchlevel >= 2))))
|
||||||
|
_raid_attrs |= RAID_FEATURE_RESHAPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes)
|
if (attributes)
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ struct dm_status_raid {
|
|||||||
char *dev_health;
|
char *dev_health;
|
||||||
/* idle, frozen, resync, recover, check, repair */
|
/* idle, frozen, resync, recover, check, repair */
|
||||||
char *sync_action;
|
char *sync_action;
|
||||||
|
uint64_t data_offset; /* RAID out-of-place reshaping */
|
||||||
};
|
};
|
||||||
|
|
||||||
int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||||
@@ -1719,7 +1720,7 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
|
|||||||
const char *raid_type,
|
const char *raid_type,
|
||||||
uint32_t region_size,
|
uint32_t region_size,
|
||||||
uint32_t stripe_size,
|
uint32_t stripe_size,
|
||||||
uint64_t rebuilds,
|
uint64_t *rebuilds,
|
||||||
uint64_t flags);
|
uint64_t flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1746,18 +1747,22 @@ struct dm_tree_node_raid_params {
|
|||||||
uint32_t region_size;
|
uint32_t region_size;
|
||||||
uint32_t stripe_size;
|
uint32_t stripe_size;
|
||||||
|
|
||||||
|
int delta_disks; /* +/- number of disks to add/remove (reshaping) */
|
||||||
|
int data_offset; /* data offset to set (out-of-place reshaping) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'rebuilds' and 'writemostly' are bitfields that signify
|
* 'rebuilds' and 'writemostly' are bitfields that signify
|
||||||
* which devices in the array are to be rebuilt or marked
|
* which devices in the array are to be rebuilt or marked
|
||||||
* writemostly. By choosing a 'uint64_t', we limit ourself
|
* writemostly. By choosing a 'uint64_t', we limit ourself
|
||||||
* to RAID arrays with 64 devices.
|
* to RAID arrays with 64 devices.
|
||||||
*/
|
*/
|
||||||
uint64_t rebuilds;
|
uint64_t rebuilds[4];
|
||||||
uint64_t writemostly;
|
uint64_t writemostly[4];
|
||||||
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
|
uint32_t writebehind; /* I/Os (kernel default COUNTER_MAX / 2) */
|
||||||
uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */
|
uint32_t sync_daemon_sleep; /* ms (kernel default = 5sec) */
|
||||||
uint32_t max_recovery_rate; /* kB/sec/disk */
|
uint32_t max_recovery_rate; /* kB/sec/disk */
|
||||||
uint32_t min_recovery_rate; /* kB/sec/disk */
|
uint32_t min_recovery_rate; /* kB/sec/disk */
|
||||||
|
uint32_t data_copies; /* RAID # of data copies */
|
||||||
uint32_t stripe_cache; /* sectors */
|
uint32_t stripe_cache; /* sectors */
|
||||||
|
|
||||||
uint64_t flags; /* [no]sync */
|
uint64_t flags; /* [no]sync */
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
#define DEV_NAME(dmt) (dmt->mangled_dev_name ? : dmt->dev_name)
|
#define DEV_NAME(dmt) (dmt->mangled_dev_name ? : dmt->dev_name)
|
||||||
#define DEV_UUID(DMT) (dmt->mangled_uuid ? : dmt->uuid)
|
#define DEV_UUID(DMT) (dmt->mangled_uuid ? : dmt->uuid)
|
||||||
|
|
||||||
|
#define RAID_BITMAP_SIZE 4
|
||||||
|
|
||||||
int mangle_string(const char *str, const char *str_name, size_t len,
|
int mangle_string(const char *str, const char *str_name, size_t len,
|
||||||
char *buf, size_t buf_len, dm_string_mangling_t mode);
|
char *buf, size_t buf_len, dm_string_mangling_t mode);
|
||||||
|
|
||||||
|
|||||||
@@ -205,11 +205,14 @@ struct load_segment {
|
|||||||
struct dm_tree_node *replicator;/* Replicator-dev */
|
struct dm_tree_node *replicator;/* Replicator-dev */
|
||||||
uint64_t rdevice_index; /* Replicator-dev */
|
uint64_t rdevice_index; /* Replicator-dev */
|
||||||
|
|
||||||
uint64_t rebuilds; /* raid */
|
int delta_disks; /* raid reshape number of disks */
|
||||||
uint64_t writemostly; /* raid */
|
int data_offset; /* raid reshape data offset on disk to set */
|
||||||
|
uint64_t rebuilds[RAID_BITMAP_SIZE]; /* raid */
|
||||||
|
uint64_t writemostly[RAID_BITMAP_SIZE]; /* raid */
|
||||||
uint32_t writebehind; /* raid */
|
uint32_t writebehind; /* raid */
|
||||||
uint32_t max_recovery_rate; /* raid kB/sec/disk */
|
uint32_t max_recovery_rate; /* raid kB/sec/disk */
|
||||||
uint32_t min_recovery_rate; /* raid kB/sec/disk */
|
uint32_t min_recovery_rate; /* raid kB/sec/disk */
|
||||||
|
uint32_t data_copies; /* raid10 data_copies */
|
||||||
|
|
||||||
struct dm_tree_node *metadata; /* Thin_pool + Cache */
|
struct dm_tree_node *metadata; /* Thin_pool + Cache */
|
||||||
struct dm_tree_node *pool; /* Thin_pool, Thin */
|
struct dm_tree_node *pool; /* Thin_pool, Thin */
|
||||||
@@ -2353,16 +2356,21 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is parameter non-zero? */
|
static int _2_if_value(unsigned p)
|
||||||
#define PARAM_IS_SET(p) ((p) ? 1 : 0)
|
{
|
||||||
|
return p ? 2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return number of bits assuming 4 * 64 bit size */
|
/* Return number of bits passed in @bits assuming 2 * 64 bit size */
|
||||||
static int _get_params_count(uint64_t bits)
|
static int _get_params_count(uint64_t *bits)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
int i = RAID_BITMAP_SIZE;
|
||||||
|
|
||||||
r += 2 * hweight32(bits & 0xFFFFFFFF);
|
while (i--) {
|
||||||
r += 2 * hweight32(bits >> 32);
|
r += 2 * hweight32(bits[i] & 0xFFFFFFFF);
|
||||||
|
r += 2 * hweight32(bits[i] >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -2373,32 +2381,60 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
|
|||||||
size_t paramsize)
|
size_t paramsize)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
uint32_t area_count = seg->area_count / 2;
|
||||||
int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */
|
int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
unsigned type = seg->type;
|
unsigned type;
|
||||||
|
|
||||||
|
if (seg->area_count % 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
|
if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
|
||||||
param_count++;
|
param_count++;
|
||||||
|
|
||||||
param_count += 2 * (PARAM_IS_SET(seg->region_size) +
|
param_count += _2_if_value(seg->data_offset) +
|
||||||
PARAM_IS_SET(seg->writebehind) +
|
_2_if_value(seg->delta_disks) +
|
||||||
PARAM_IS_SET(seg->min_recovery_rate) +
|
_2_if_value(seg->region_size) +
|
||||||
PARAM_IS_SET(seg->max_recovery_rate));
|
_2_if_value(seg->writebehind) +
|
||||||
|
_2_if_value(seg->min_recovery_rate) +
|
||||||
|
_2_if_value(seg->max_recovery_rate) +
|
||||||
|
_2_if_value(seg->data_copies > 1);
|
||||||
|
|
||||||
/* rebuilds and writemostly are 64 bits */
|
/* rebuilds and writemostly are BITMAP_SIZE * 64 bits */
|
||||||
param_count += _get_params_count(seg->rebuilds);
|
param_count += _get_params_count(seg->rebuilds);
|
||||||
param_count += _get_params_count(seg->writemostly);
|
param_count += _get_params_count(seg->writemostly);
|
||||||
|
|
||||||
if ((type == SEG_RAID1) && seg->stripe_size)
|
if ((seg->type == SEG_RAID1) && seg->stripe_size)
|
||||||
log_error("WARNING: Ignoring RAID1 stripe size");
|
log_info("WARNING: Ignoring RAID1 stripe size");
|
||||||
|
|
||||||
/* Kernel only expects "raid0", not "raid0_meta" */
|
/* Kernel only expects "raid0", not "raid0_meta" */
|
||||||
|
type = seg->type;
|
||||||
if (type == SEG_RAID0_META)
|
if (type == SEG_RAID0_META)
|
||||||
type = SEG_RAID0;
|
type = SEG_RAID0;
|
||||||
|
#if 0
|
||||||
|
/* Kernel only expects "raid10", not "raid10_{far,offset}" */
|
||||||
|
else if (type == SEG_RAID10_FAR ||
|
||||||
|
type == SEG_RAID10_OFFSET) {
|
||||||
|
param_count += 2;
|
||||||
|
type = SEG_RAID10_NEAR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EMIT_PARAMS(pos, "%s %d %u", _dm_segtypes[type].target,
|
EMIT_PARAMS(pos, "%s %d %u",
|
||||||
|
// type == SEG_RAID10_NEAR ? "raid10" : _dm_segtypes[type].target,
|
||||||
|
type == SEG_RAID10 ? "raid10" : _dm_segtypes[type].target,
|
||||||
param_count, seg->stripe_size);
|
param_count, seg->stripe_size);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (seg->type == SEG_RAID10_FAR)
|
||||||
|
EMIT_PARAMS(pos, " raid10_format far");
|
||||||
|
else if (seg->type == SEG_RAID10_OFFSET)
|
||||||
|
EMIT_PARAMS(pos, " raid10_format offset");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (seg->data_copies > 1 && type == SEG_RAID10)
|
||||||
|
EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
|
||||||
|
|
||||||
if (seg->flags & DM_NOSYNC)
|
if (seg->flags & DM_NOSYNC)
|
||||||
EMIT_PARAMS(pos, " nosync");
|
EMIT_PARAMS(pos, " nosync");
|
||||||
else if (seg->flags & DM_FORCESYNC)
|
else if (seg->flags & DM_FORCESYNC)
|
||||||
@@ -2407,27 +2443,38 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
|
|||||||
if (seg->region_size)
|
if (seg->region_size)
|
||||||
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
|
EMIT_PARAMS(pos, " region_size %u", seg->region_size);
|
||||||
|
|
||||||
for (i = 0; i < (seg->area_count / 2); i++)
|
/* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
|
||||||
if (seg->rebuilds & (1ULL << i))
|
if (seg->data_offset)
|
||||||
|
EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
|
||||||
|
|
||||||
|
if (seg->delta_disks)
|
||||||
|
EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
|
||||||
|
|
||||||
|
for (i = 0; i < area_count; i++)
|
||||||
|
if (seg->rebuilds[i/64] & (1ULL << (i%64)))
|
||||||
EMIT_PARAMS(pos, " rebuild %u", i);
|
EMIT_PARAMS(pos, " rebuild %u", i);
|
||||||
|
|
||||||
if (seg->min_recovery_rate)
|
for (i = 0; i < area_count; i++)
|
||||||
EMIT_PARAMS(pos, " min_recovery_rate %u",
|
if (seg->writemostly[i/64] & (1ULL << (i%64)))
|
||||||
seg->min_recovery_rate);
|
|
||||||
|
|
||||||
if (seg->max_recovery_rate)
|
|
||||||
EMIT_PARAMS(pos, " max_recovery_rate %u",
|
|
||||||
seg->max_recovery_rate);
|
|
||||||
|
|
||||||
for (i = 0; i < (seg->area_count / 2); i++)
|
|
||||||
if (seg->writemostly & (1ULL << i))
|
|
||||||
EMIT_PARAMS(pos, " write_mostly %u", i);
|
EMIT_PARAMS(pos, " write_mostly %u", i);
|
||||||
|
|
||||||
if (seg->writebehind)
|
if (seg->writebehind)
|
||||||
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
|
EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Has to be before "min_recovery_rate" or the kernels
|
||||||
|
* check will fail when both set and min > previous max
|
||||||
|
*/
|
||||||
|
if (seg->max_recovery_rate)
|
||||||
|
EMIT_PARAMS(pos, " max_recovery_rate %u",
|
||||||
|
seg->max_recovery_rate);
|
||||||
|
|
||||||
|
if (seg->min_recovery_rate)
|
||||||
|
EMIT_PARAMS(pos, " min_recovery_rate %u",
|
||||||
|
seg->min_recovery_rate);
|
||||||
|
|
||||||
/* Print number of metadata/data device pairs */
|
/* Print number of metadata/data device pairs */
|
||||||
EMIT_PARAMS(pos, " %u", seg->area_count/2);
|
EMIT_PARAMS(pos, " %u", area_count);
|
||||||
|
|
||||||
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
|
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
|
||||||
return_0;
|
return_0;
|
||||||
@@ -3267,11 +3314,14 @@ int dm_tree_node_add_raid_target_with_params(struct dm_tree_node *node,
|
|||||||
seg->region_size = p->region_size;
|
seg->region_size = p->region_size;
|
||||||
seg->stripe_size = p->stripe_size;
|
seg->stripe_size = p->stripe_size;
|
||||||
seg->area_count = 0;
|
seg->area_count = 0;
|
||||||
seg->rebuilds = p->rebuilds;
|
seg->delta_disks = p->delta_disks;
|
||||||
seg->writemostly = p->writemostly;
|
seg->data_offset = p->data_offset;
|
||||||
|
memcpy(seg->rebuilds, p->rebuilds, sizeof(seg->rebuilds));
|
||||||
|
memcpy(seg->writemostly, p->writemostly, sizeof(seg->writemostly));
|
||||||
seg->writebehind = p->writebehind;
|
seg->writebehind = p->writebehind;
|
||||||
seg->min_recovery_rate = p->min_recovery_rate;
|
seg->min_recovery_rate = p->min_recovery_rate;
|
||||||
seg->max_recovery_rate = p->max_recovery_rate;
|
seg->max_recovery_rate = p->max_recovery_rate;
|
||||||
|
seg->data_copies = p->data_copies;
|
||||||
seg->flags = p->flags;
|
seg->flags = p->flags;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -3282,17 +3332,18 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
|
|||||||
const char *raid_type,
|
const char *raid_type,
|
||||||
uint32_t region_size,
|
uint32_t region_size,
|
||||||
uint32_t stripe_size,
|
uint32_t stripe_size,
|
||||||
uint64_t rebuilds,
|
uint64_t *rebuilds,
|
||||||
uint64_t flags)
|
uint64_t flags)
|
||||||
{
|
{
|
||||||
struct dm_tree_node_raid_params params = {
|
struct dm_tree_node_raid_params params = {
|
||||||
.raid_type = raid_type,
|
.raid_type = raid_type,
|
||||||
.region_size = region_size,
|
.region_size = region_size,
|
||||||
.stripe_size = stripe_size,
|
.stripe_size = stripe_size,
|
||||||
.rebuilds = rebuilds,
|
|
||||||
.flags = flags
|
.flags = flags
|
||||||
};
|
};
|
||||||
|
|
||||||
|
memcpy(params.rebuilds, rebuilds, sizeof(params.rebuilds));
|
||||||
|
|
||||||
return dm_tree_node_add_raid_target_with_params(node, size, ¶ms);
|
return dm_tree_node_add_raid_target_with_params(node, size, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ static unsigned _count_fields(const char *p)
|
|||||||
* <raid_type> <#devs> <health_str> <sync_ratio>
|
* <raid_type> <#devs> <health_str> <sync_ratio>
|
||||||
* Versions 1.5.0+ (6 fields):
|
* Versions 1.5.0+ (6 fields):
|
||||||
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
|
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
|
||||||
|
* Versions 1.9.0+ (7 fields):
|
||||||
|
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt> <data_offset>
|
||||||
*/
|
*/
|
||||||
int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||||
struct dm_status_raid **status)
|
struct dm_status_raid **status)
|
||||||
@@ -147,6 +149,22 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
|||||||
if (sscanf(p, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2)
|
if (sscanf(p, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2)
|
||||||
goto_bad;
|
goto_bad;
|
||||||
|
|
||||||
|
if (num_fields < 7)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All pre-1.9.0 version parameters are read. Now we check
|
||||||
|
* for additional 1.9.0+ parameters (i.e. nr_fields at least 7).
|
||||||
|
*
|
||||||
|
* Note that data_offset will be 0 if the
|
||||||
|
* kernel returns a pre-1.9.0 status.
|
||||||
|
*/
|
||||||
|
msg_fields = "<data_offset>";
|
||||||
|
if (!(p = _skip_fields(params, 6))) /* skip pre-1.9.0 params */
|
||||||
|
goto bad;
|
||||||
|
if (sscanf(p, "%" PRIu64, &s->data_offset) != 1)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*status = s;
|
*status = s;
|
||||||
|
|
||||||
|
|||||||
108
man/lvm.8.in
108
man/lvm.8.in
@@ -484,70 +484,48 @@ directly.
|
|||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.
|
.
|
||||||
.nh
|
.nh
|
||||||
.BR lvm (8)
|
.BR lvm.conf (5),
|
||||||
.BR lvm.conf (5)
|
.BR lvmcache (7),
|
||||||
.BR lvmconfig (8)
|
.BR lvmreport(7),
|
||||||
|
.BR lvmthin (7),
|
||||||
.BR pvchange (8)
|
.BR clvmd (8),
|
||||||
.BR pvck (8)
|
|
||||||
.BR pvcreate (8)
|
|
||||||
.BR pvdisplay (8)
|
|
||||||
.BR pvmove (8)
|
|
||||||
.BR pvremove (8)
|
|
||||||
.BR pvresize (8)
|
|
||||||
.BR pvs (8)
|
|
||||||
.BR pvscan (8)
|
|
||||||
|
|
||||||
.BR vgcfgbackup (8)
|
|
||||||
.BR vgcfgrestore (8)
|
|
||||||
.BR vgchange (8)
|
|
||||||
.BR vgck (8)
|
|
||||||
.BR vgcreate (8)
|
|
||||||
.BR vgconvert (8)
|
|
||||||
.BR vgdisplay (8)
|
|
||||||
.BR vgexport (8)
|
|
||||||
.BR vgextend (8)
|
|
||||||
.BR vgimport (8)
|
|
||||||
.BR vgimportclone (8)
|
|
||||||
.BR vgmerge (8)
|
|
||||||
.BR vgmknodes (8)
|
|
||||||
.BR vgreduce (8)
|
|
||||||
.BR vgremove (8)
|
|
||||||
.BR vgrename (8)
|
|
||||||
.BR vgs (8)
|
|
||||||
.BR vgscan (8)
|
|
||||||
.BR vgsplit (8)
|
|
||||||
|
|
||||||
.BR lvcreate (8)
|
|
||||||
.BR lvchange (8)
|
|
||||||
.BR lvconvert (8)
|
|
||||||
.BR lvdisplay (8)
|
|
||||||
.BR lvextend (8)
|
|
||||||
.BR lvreduce (8)
|
|
||||||
.BR lvremove (8)
|
|
||||||
.BR lvrename (8)
|
|
||||||
.BR lvresize (8)
|
|
||||||
.BR lvs (8)
|
|
||||||
.BR lvscan (8)
|
|
||||||
|
|
||||||
.BR lvm2-activation-generator (8)
|
|
||||||
.BR blkdeactivate (8)
|
|
||||||
.BR lvmdump (8)
|
|
||||||
|
|
||||||
.BR dmeventd (8)
|
|
||||||
.BR lvmetad (8)
|
|
||||||
.BR lvmpolld (8)
|
|
||||||
.BR lvmlockd (8)
|
|
||||||
.BR lvmlockctl (8)
|
|
||||||
.BR clvmd (8)
|
|
||||||
.BR cmirrord (8)
|
|
||||||
.BR lvmdbusd (8)
|
|
||||||
|
|
||||||
.BR lvmsystemid (7)
|
|
||||||
.BR lvmreport (7)
|
|
||||||
.BR lvmraid (7)
|
|
||||||
.BR lvmthin (7)
|
|
||||||
.BR lvmcache (7)
|
|
||||||
|
|
||||||
.BR dmsetup (8),
|
.BR dmsetup (8),
|
||||||
|
.BR lvchange (8),
|
||||||
|
.BR lvcreate (8),
|
||||||
|
.BR lvdisplay (8),
|
||||||
|
.BR lvextend (8),
|
||||||
|
.BR lvmchange (8),
|
||||||
|
.BR lvmconfig (8),
|
||||||
|
.BR lvmdiskscan (8),
|
||||||
|
.BR lvreduce (8),
|
||||||
|
.BR lvremove (8),
|
||||||
|
.BR lvrename (8),
|
||||||
|
.BR lvresize (8),
|
||||||
|
.BR lvs (8),
|
||||||
|
.BR lvscan (8),
|
||||||
|
.BR pvchange (8),
|
||||||
|
.BR pvck (8),
|
||||||
|
.BR pvcreate (8),
|
||||||
|
.BR pvdisplay (8),
|
||||||
|
.BR pvmove (8),
|
||||||
|
.BR pvremove (8),
|
||||||
|
.BR pvs (8),
|
||||||
|
.BR pvscan (8),
|
||||||
|
.BR vgcfgbackup (8),
|
||||||
|
.BR vgchange (8),
|
||||||
|
.BR vgck (8),
|
||||||
|
.BR vgconvert (8),
|
||||||
|
.BR vgcreate (8),
|
||||||
|
.BR vgdisplay (8),
|
||||||
|
.BR vgextend (8),
|
||||||
|
.BR vgimport (8),
|
||||||
|
.BR vgimportclone (8),
|
||||||
|
.BR vgmerge (8),
|
||||||
|
.BR vgmknodes (8),
|
||||||
|
.BR vgreduce (8),
|
||||||
|
.BR vgremove (8),
|
||||||
|
.BR vgrename (8),
|
||||||
|
.BR vgs (8),
|
||||||
|
.BR vgscan (8),
|
||||||
|
.BR vgsplit (8),
|
||||||
.BR readline (3)
|
.BR readline (3)
|
||||||
|
|||||||
@@ -866,7 +866,7 @@ common_dev_() {
|
|||||||
else
|
else
|
||||||
test -z "${offsets[@]}" && offsets="0:"
|
test -z "${offsets[@]}" && offsets="0:"
|
||||||
fi ;;
|
fi ;;
|
||||||
error|zero) offsets=${@:3}
|
error) offsets=${@:3}
|
||||||
test -z "${offsets[@]}" && offsets="0:" ;;
|
test -z "${offsets[@]}" && offsets="0:" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -893,8 +893,8 @@ common_dev_() {
|
|||||||
case "$tgtype" in
|
case "$tgtype" in
|
||||||
delay)
|
delay)
|
||||||
echo "$from $len delay $pvdev $(($pos + $offset)) $read_ms $pvdev $(($pos + $offset)) $write_ms" ;;
|
echo "$from $len delay $pvdev $(($pos + $offset)) $read_ms $pvdev $(($pos + $offset)) $write_ms" ;;
|
||||||
error|zero)
|
error)
|
||||||
echo "$from $len $tgtype" ;;
|
echo "$from $len error" ;;
|
||||||
esac
|
esac
|
||||||
pos=$(($pos + $len))
|
pos=$(($pos + $len))
|
||||||
done > "$name.devtable"
|
done > "$name.devtable"
|
||||||
@@ -1013,23 +1013,12 @@ restore_from_devtable() {
|
|||||||
#
|
#
|
||||||
# Convert device to device with errors
|
# Convert device to device with errors
|
||||||
# Takes the list of pairs of error segment from:len
|
# Takes the list of pairs of error segment from:len
|
||||||
# Combination with zero or delay is unsupported
|
# Original device table is replace with multiple lines
|
||||||
# Original device table is replaced with multiple lines
|
|
||||||
# i.e. error_dev "$dev1" 8:32 96:8
|
# i.e. error_dev "$dev1" 8:32 96:8
|
||||||
error_dev() {
|
error_dev() {
|
||||||
common_dev_ error "$@"
|
common_dev_ error "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# Convert existing device to a device with zero segments
|
|
||||||
# Takes the list of pairs of zero segment from:len
|
|
||||||
# Combination with error or delay is unsupported
|
|
||||||
# Original device table is replaced with multiple lines
|
|
||||||
# i.e. zero_dev "$dev1" 8:32 96:8
|
|
||||||
zero_dev() {
|
|
||||||
common_dev_ zero "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_dev() {
|
backup_dev() {
|
||||||
local dev
|
local dev
|
||||||
|
|
||||||
@@ -1317,7 +1306,7 @@ udev_wait() {
|
|||||||
wait_for_sync() {
|
wait_for_sync() {
|
||||||
local i
|
local i
|
||||||
for i in {1..100} ; do
|
for i in {1..100} ; do
|
||||||
check in_sync $1 $2 && return
|
check in_sync $1 $2 $3 && return
|
||||||
sleep .2
|
sleep .2
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ linear() {
|
|||||||
$(lvl $lv -o+devices)
|
$(lvl $lv -o+devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
# in_sync <VG> <LV>
|
# in_sync <VG> <LV> <ignore 'a'>
|
||||||
# Works for "mirror" and "raid*"
|
# Works for "mirror" and "raid*"
|
||||||
in_sync() {
|
in_sync() {
|
||||||
local a
|
local a
|
||||||
@@ -187,8 +187,11 @@ in_sync() {
|
|||||||
local type
|
local type
|
||||||
local snap=""
|
local snap=""
|
||||||
local lvm_name="$1/$2"
|
local lvm_name="$1/$2"
|
||||||
|
local ignore_a="$3"
|
||||||
local dm_name=$(echo $lvm_name | sed s:-:--: | sed s:/:-:)
|
local dm_name=$(echo $lvm_name | sed s:-:--: | sed s:/:-:)
|
||||||
|
|
||||||
|
[ -z "$ignore_a" ] && ignore_a=0
|
||||||
|
|
||||||
a=( $(dmsetup status $dm_name) ) || \
|
a=( $(dmsetup status $dm_name) ) || \
|
||||||
die "Unable to get sync status of $1"
|
die "Unable to get sync status of $1"
|
||||||
|
|
||||||
@@ -225,7 +228,7 @@ in_sync() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ ${a[$(($idx - 1))]} =~ a ]] && \
|
[[ ${a[$(($idx - 1))]} =~ a ]] && [ $ignore_a -eq 0 ] && \
|
||||||
die "$lvm_name ($type$snap) in-sync, but 'a' characters in health status"
|
die "$lvm_name ($type$snap) in-sync, but 'a' characters in health status"
|
||||||
|
|
||||||
echo "$lvm_name ($type$snap) is in-sync \"${a[@]}\""
|
echo "$lvm_name ($type$snap) is in-sync \"${a[@]}\""
|
||||||
@@ -310,6 +313,12 @@ lv_field() {
|
|||||||
die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
|
die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_first_seg_field() {
|
||||||
|
local actual=$(get lv_first_seg_field "$1" "$2" "${@:4}")
|
||||||
|
test "$actual" = "$3" || \
|
||||||
|
die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
|
||||||
|
}
|
||||||
|
|
||||||
lvh_field() {
|
lvh_field() {
|
||||||
local actual=$(get lvh_field "$1" "$2" "${@:4}")
|
local actual=$(get lvh_field "$1" "$2" "${@:4}")
|
||||||
test "$actual" = "$3" || \
|
test "$actual" = "$3" || \
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ lv_field() {
|
|||||||
trim_ "$r"
|
trim_ "$r"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_first_seg_field() {
|
||||||
|
local r=$(lvs --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1" | head -1)
|
||||||
|
trim_ "$r"
|
||||||
|
}
|
||||||
|
|
||||||
lvh_field() {
|
lvh_field() {
|
||||||
local r=$(lvs -H --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1")
|
local r=$(lvs -H --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1")
|
||||||
trim_ "$r"
|
trim_ "$r"
|
||||||
|
|||||||
199
test/shell/lvconvert-raid-reshape.sh
Normal file
199
test/shell/lvconvert-raid-reshape.sh
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright (C) 2017 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
# of the GNU General Public License v.2.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA
|
||||||
|
|
||||||
|
SKIP_WITH_LVMLOCKD=1
|
||||||
|
SKIP_WITH_LVMPOLLD=1
|
||||||
|
|
||||||
|
. lib/inittest
|
||||||
|
|
||||||
|
which mkfs.ext4 || skip
|
||||||
|
aux have_raid 1 10 2 || skip
|
||||||
|
|
||||||
|
aux prepare_vg 64
|
||||||
|
|
||||||
|
function _lvcreate
|
||||||
|
{
|
||||||
|
local level=$1
|
||||||
|
local req_stripes=$2
|
||||||
|
local stripes=$3
|
||||||
|
local size=$4
|
||||||
|
local vg=$5
|
||||||
|
local lv=$6
|
||||||
|
|
||||||
|
lvcreate -y -aey --type $level -i $req_stripes -L $size -n $lv $vg
|
||||||
|
check lv_first_seg_field $vg/$lv segtype "$level"
|
||||||
|
check lv_first_seg_field $vg/$lv stripes $stripes
|
||||||
|
mkfs.ext4 "$DM_DEV_DIR/$vg/$lv"
|
||||||
|
fsck -fn "$DM_DEV_DIR/$vg/$lv"
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lvconvert
|
||||||
|
{
|
||||||
|
local req_level=$1
|
||||||
|
local level=$2
|
||||||
|
local stripes=$3
|
||||||
|
local vg=$4
|
||||||
|
local lv=$5
|
||||||
|
local region_size=$6
|
||||||
|
local wait_and_check=1
|
||||||
|
local R=""
|
||||||
|
|
||||||
|
[ -n "$region_size" ] && R="-R $region_size"
|
||||||
|
[ "${level:0:7}" = "striped" ] && wait_and_check=0
|
||||||
|
[ "${level:0:5}" = "raid0" ] && wait_and_check=0
|
||||||
|
|
||||||
|
lvconvert -y --ty $req_level $R $vg/$lv
|
||||||
|
[ $? -ne 0 ] && return $?
|
||||||
|
check lv_first_seg_field $vg/$lv segtype "$level"
|
||||||
|
check lv_first_seg_field $vg/$lv stripes $stripes
|
||||||
|
[ -n "$region_size" ] && check lv_field $vg/$lv regionsize $region_size
|
||||||
|
if [ "$wait_and_check" -eq 1 ]
|
||||||
|
then
|
||||||
|
fsck -fn "$DM_DEV_DIR/$vg/$lv"
|
||||||
|
aux wait_for_sync $vg $lv
|
||||||
|
fi
|
||||||
|
fsck -fn "$DM_DEV_DIR/$vg/$lv"
|
||||||
|
}
|
||||||
|
|
||||||
|
function _reshape_layout
|
||||||
|
{
|
||||||
|
local type=$1
|
||||||
|
shift
|
||||||
|
local stripes=$1
|
||||||
|
shift
|
||||||
|
local vg=$1
|
||||||
|
shift
|
||||||
|
local lv=$1
|
||||||
|
shift
|
||||||
|
local opts="$*"
|
||||||
|
local ignore_a_chars=0
|
||||||
|
|
||||||
|
[[ "$opts" =~ "--stripes" ]] && ignore_a_chars=1
|
||||||
|
|
||||||
|
lvconvert -vvvv -y --ty $type $opts $vg/$lv
|
||||||
|
check lv_first_seg_field $vg/$lv segtype "$type"
|
||||||
|
check lv_first_seg_field $vg/$lv stripes $stripes
|
||||||
|
aux wait_for_sync $vg $lv $ignore_a_chars
|
||||||
|
fsck -fn "$DM_DEV_DIR/$vg/$lv"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Delay leg so that rebuilding status characters
|
||||||
|
# can be read before resync finished too quick.
|
||||||
|
# aux delay_dev "$dev1" 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start out with raid5(_ls)
|
||||||
|
#
|
||||||
|
|
||||||
|
# Create 3-way striped raid5 (4 legs total)
|
||||||
|
_lvcreate raid5_ls 3 4 16M $vg $lv1
|
||||||
|
check lv_first_seg_field $vg/$lv1 segtype "raid5_ls"
|
||||||
|
aux wait_for_sync $vg $lv1
|
||||||
|
|
||||||
|
# Reshape it to 256K stripe size
|
||||||
|
_reshape_layout raid5_ls 4 $vg $lv1 --stripesize 256K
|
||||||
|
check lv_first_seg_field $vg/$lv1 stripesize "256.00k"
|
||||||
|
|
||||||
|
# Convert raid5(_n) -> striped
|
||||||
|
not _lvconvert striped striped 3 $vg $lv1 512k
|
||||||
|
_reshape_layout raid5_n 4 $vg $lv1
|
||||||
|
_lvconvert striped striped 3 $vg $lv1
|
||||||
|
|
||||||
|
# Convert striped -> raid5_n
|
||||||
|
_lvconvert raid5_n raid5_n 4 $vg $lv1 "" 1
|
||||||
|
|
||||||
|
# Convert raid5_n -> raid5_ls
|
||||||
|
_reshape_layout raid5_ls 4 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid5_ls to 5 stripes
|
||||||
|
_reshape_layout raid5_ls 6 $vg $lv1 --stripes 5
|
||||||
|
|
||||||
|
# Convert raid5_ls back to 3 stripes
|
||||||
|
_reshape_layout raid5_ls 6 $vg $lv1 --stripes 3 --force
|
||||||
|
_reshape_layout raid5_ls 4 $vg $lv1 --stripes 3
|
||||||
|
|
||||||
|
# Convert raid5_ls to 7 stripes
|
||||||
|
_reshape_layout raid5_ls 8 $vg $lv1 --stripes 7
|
||||||
|
|
||||||
|
# Convert raid5_ls to 9 stripes
|
||||||
|
_reshape_layout raid5_ls 10 $vg $lv1 --stripes 9
|
||||||
|
|
||||||
|
# Convert raid5_ls to 14 stripes
|
||||||
|
_reshape_layout raid5_ls 15 $vg $lv1 --stripes 14
|
||||||
|
|
||||||
|
# Convert raid5_ls to 63 stripes
|
||||||
|
_reshape_layout raid5_ls 64 $vg $lv1 --stripes 63
|
||||||
|
|
||||||
|
# Convert raid5_ls back to 27 stripes
|
||||||
|
_reshape_layout raid5_ls 64 $vg $lv1 --stripes 27 --force
|
||||||
|
_reshape_layout raid5_ls 28 $vg $lv1 --stripes 27
|
||||||
|
|
||||||
|
# Convert raid5_ls back to 4 stripes
|
||||||
|
_reshape_layout raid5_ls 28 $vg $lv1 --stripes 4 --force
|
||||||
|
_reshape_layout raid5_ls 5 $vg $lv1 --stripes 4
|
||||||
|
|
||||||
|
# Convert raid5_ls back to 3 stripes
|
||||||
|
_reshape_layout raid5_ls 5 $vg $lv1 --stripes 3 --force
|
||||||
|
_reshape_layout raid5_ls 4 $vg $lv1 --stripes 3
|
||||||
|
|
||||||
|
# Convert raid5_ls -> raid5_rs
|
||||||
|
_reshape_layout raid5_rs 4 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid5_rs -> raid5_la
|
||||||
|
_reshape_layout raid5_la 4 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid5_la -> raid5_ra
|
||||||
|
_reshape_layout raid5_ra 4 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid5_ra -> raid6_ra_6
|
||||||
|
_lvconvert raid6_ra_6 raid6_ra_6 5 $vg $lv1 "4.00m" 1
|
||||||
|
|
||||||
|
# Convert raid5_la -> raid6(_zr)
|
||||||
|
_reshape_layout raid6 5 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid6(_zr) -> raid6_nc
|
||||||
|
_reshape_layout raid6_nc 5 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid6(_nc) -> raid6_nr
|
||||||
|
_reshape_layout raid6_nr 5 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid6_nr) -> raid6_rs_6
|
||||||
|
_reshape_layout raid6_rs_6 5 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid6_rs_6 to 5 stripes
|
||||||
|
_reshape_layout raid6_rs_6 7 $vg $lv1 --stripes 5
|
||||||
|
|
||||||
|
# Convert raid6_rs_6 to 4 stripes
|
||||||
|
_reshape_layout raid6_rs_6 7 $vg $lv1 --stripes 4 --force
|
||||||
|
_reshape_layout raid6_rs_6 6 $vg $lv1 --stripes 4
|
||||||
|
check lv_first_seg_field $vg/$lv1 stripesize "256.00k"
|
||||||
|
|
||||||
|
# Convert raid6_rs_6 to raid6_n_6
|
||||||
|
_reshape_layout raid6_n_6 6 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid6_n_6 -> striped
|
||||||
|
_lvconvert striped striped 4 $vg $lv1
|
||||||
|
check lv_first_seg_field $vg/$lv1 stripesize "256.00k"
|
||||||
|
|
||||||
|
# Convert striped -> raid10(_near)
|
||||||
|
_lvconvert raid10 raid10 8 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid10 to 10 stripes and 64K stripesize
|
||||||
|
# FIXME: change once we support odd numbers of raid10 stripes
|
||||||
|
not _reshape_layout raid10 9 $vg $lv1 --stripes 9 --stripesize 64K
|
||||||
|
_reshape_layout raid10 10 $vg $lv1 --stripes 10 --stripesize 64K
|
||||||
|
check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
|
||||||
|
|
||||||
|
# Convert raid6_n_6 -> striped
|
||||||
|
_lvconvert striped striped 5 $vg $lv1
|
||||||
|
check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
|
||||||
|
|
||||||
|
vgremove -ff $vg
|
||||||
@@ -117,8 +117,7 @@ fsck -fn "$DM_DEV_DIR/$vg/$lv1"
|
|||||||
lvconvert -m 4 -R 128K $vg/$lv1
|
lvconvert -m 4 -R 128K $vg/$lv1
|
||||||
check lv_field $vg/$lv1 segtype "raid1"
|
check lv_field $vg/$lv1 segtype "raid1"
|
||||||
check lv_field $vg/$lv1 stripes 5
|
check lv_field $vg/$lv1 stripes 5
|
||||||
# FIXME: once lv_raid_chanage_image_count() supports region_size changes
|
check lv_field $vg/$lv1 regionsize "128.00k"
|
||||||
not check lv_field $vg/$lv1 regionsize "128.00k"
|
|
||||||
fsck -fn "$DM_DEV_DIR/$vg/$lv1"
|
fsck -fn "$DM_DEV_DIR/$vg/$lv1"
|
||||||
aux wait_for_sync $vg $lv1
|
aux wait_for_sync $vg $lv1
|
||||||
fsck -fn "$DM_DEV_DIR/$vg/$lv1"
|
fsck -fn "$DM_DEV_DIR/$vg/$lv1"
|
||||||
@@ -258,7 +257,13 @@ _lvconvert raid0 raid0 3 $vg $lv1
|
|||||||
# Convert raid0 -> raid10
|
# Convert raid0 -> raid10
|
||||||
_lvconvert raid10 raid10 6 $vg $lv1
|
_lvconvert raid10 raid10 6 $vg $lv1
|
||||||
|
|
||||||
# Convert raid10 -> raid0
|
# Convert raid10 -> raid0_meta
|
||||||
|
_lvconvert raid0_meta raid0_meta 3 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid0_meta -> raid5
|
||||||
|
_lvconvert raid5_n raid5_n 4 $vg $lv1
|
||||||
|
|
||||||
|
# Convert raid5_n -> raid0_meta
|
||||||
_lvconvert raid0_meta raid0_meta 3 $vg $lv1
|
_lvconvert raid0_meta raid0_meta 3 $vg $lv1
|
||||||
|
|
||||||
# Convert raid0_meta -> raid10
|
# Convert raid0_meta -> raid10
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ test_pvmove_resume() {
|
|||||||
# next LV on same VG and differetnt PV (we want to test 2 pvmoves per VG)
|
# next LV on same VG and differetnt PV (we want to test 2 pvmoves per VG)
|
||||||
lvcreate -an -Zn -l30 -n $lv2 $vg "$dev3"
|
lvcreate -an -Zn -l30 -n $lv2 $vg "$dev3"
|
||||||
|
|
||||||
aux delay_dev "$dev4" 0 250 $(get first_extent_sector "$dev4"):
|
aux delay_dev "$dev4" 0 250
|
||||||
test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; }
|
test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; }
|
||||||
aux delay_dev "$dev5" 0 250 $(get first_extent_sector "$dev5"):
|
aux delay_dev "$dev5" 0 250
|
||||||
|
|
||||||
pvmove -i5 "$dev1" "$dev4" &
|
pvmove -i5 "$dev1" "$dev4" &
|
||||||
PVMOVE=$!
|
PVMOVE=$!
|
||||||
|
|||||||
11
tools/args.h
11
tools/args.h
@@ -646,16 +646,7 @@ arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0,
|
|||||||
"Avoids certain device scanning during command processing. Do not use.\n")
|
"Avoids certain device scanning during command processing. Do not use.\n")
|
||||||
|
|
||||||
arg(type_ARG, '\0', "type", segtype_VAL, 0, 0,
|
arg(type_ARG, '\0', "type", segtype_VAL, 0, 0,
|
||||||
"Specifies an LV type, or \"segment type\".\n"
|
"Specifies an LV type, or \"segment type\".\n")
|
||||||
"See usage definitions for specific ways to use these types.\n"
|
|
||||||
"For more information about redundancy and performance (\\fBraid\\fP<N>, \\fBmirror\\fP, \\fBstriped\\fP, \\fBlinear\\fP) see \\fBlvmraid\\fP(7).\n"
|
|
||||||
"For thin provisioning (\\fBthin\\fP, \\fBthin-pool\\fP) see \\fBlvmthin\\fP(7).\n"
|
|
||||||
"For performance caching (\\fBcache\\fP, \\fBcache-pool\\fP) see \\fBlvmcache\\fP(7).\n"
|
|
||||||
"For copy-on-write snapshots (\\fBsnapshot\\fP) see usage definitions.\n"
|
|
||||||
"Several commands omit an explicit type option because the type\n"
|
|
||||||
"is inferred from other options or shortcuts\n"
|
|
||||||
"(e.g. --stripes, --mirrors, --snapshot, --virtualsize, --thin, --cache).\n"
|
|
||||||
"Use inferred types with care because it can lead to unexpected results.\n")
|
|
||||||
|
|
||||||
arg(unbuffered_ARG, '\0', "unbuffered", 0, 0, 0,
|
arg(unbuffered_ARG, '\0', "unbuffered", 0, 0, 0,
|
||||||
"Produce output immediately without sorting or aligning the columns properly.\n")
|
"Produce output immediately without sorting or aligning the columns properly.\n")
|
||||||
|
|||||||
@@ -190,6 +190,20 @@ OO_ALL: --commandprofile String, --config String, --debug,
|
|||||||
--driverloaded Bool, --help, --longhelp, --profile String, --quiet,
|
--driverloaded Bool, --help, --longhelp, --profile String, --quiet,
|
||||||
--verbose, --version, --yes, --test
|
--verbose, --version, --yes, --test
|
||||||
|
|
||||||
|
#
|
||||||
|
# This list only applies to printing the usage text.
|
||||||
|
# These common options are displayed once at the end of
|
||||||
|
# a given command's usage. This is done to avoid excessive
|
||||||
|
# repetition of common options, which may obscure the more
|
||||||
|
# interesting and relevant parts of a common prototype.
|
||||||
|
# This definition is *only* used when generating the command
|
||||||
|
# usage strings, and is the basis for the division between
|
||||||
|
# the "usage" and "usage_common" strings. This OO defn does
|
||||||
|
# not relate to which optional opts are accepted by commands,
|
||||||
|
# which is defined by the OO line.
|
||||||
|
#
|
||||||
|
OO_USAGE_COMMON: OO_ALL, --force, --noudevsync
|
||||||
|
|
||||||
#
|
#
|
||||||
# options for pvs, lvs, vgs, fullreport
|
# options for pvs, lvs, vgs, fullreport
|
||||||
#
|
#
|
||||||
@@ -345,6 +359,13 @@ ID: lvconvert_raid_types
|
|||||||
DESC: Convert LV to raid.
|
DESC: Convert LV to raid.
|
||||||
RULE: all not lv_is_locked lv_is_pvmove
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
|
|
||||||
|
lvconvert --type raid LV_raid
|
||||||
|
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
|
||||||
|
ID: lvconvert_raid_types
|
||||||
|
DESC: Convert raid LV to different layout algorithm.
|
||||||
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
|
RULE: all not LV_raid0 LV_raid1
|
||||||
|
|
||||||
lvconvert --mirrors SNumber LV
|
lvconvert --mirrors SNumber LV
|
||||||
OO: OO_LVCONVERT_RAID, OO_LVCONVERT, --mirrorlog MirrorLog
|
OO: OO_LVCONVERT_RAID, OO_LVCONVERT, --mirrorlog MirrorLog
|
||||||
OP: PV ...
|
OP: PV ...
|
||||||
@@ -352,6 +373,21 @@ ID: lvconvert_raid_types
|
|||||||
DESC: Convert LV to raid1 or mirror, or change number of mirror images.
|
DESC: Convert LV to raid1 or mirror, or change number of mirror images.
|
||||||
RULE: all not lv_is_locked lv_is_pvmove
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
|
|
||||||
|
lvconvert --stripes_long SNumber LV_raid
|
||||||
|
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
|
||||||
|
OP: PV ...
|
||||||
|
ID: lvconvert_raid_types
|
||||||
|
DESC: Convert raid LV to change number of stripe images.
|
||||||
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
|
RULE: all not LV_raid0 LV_raid1
|
||||||
|
|
||||||
|
lvconvert --stripesize SizeKB LV_raid
|
||||||
|
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
|
||||||
|
ID: lvconvert_raid_types
|
||||||
|
DESC: Convert raid LV to change the stripe size.
|
||||||
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
|
RULE: all not LV_raid0 LV_raid1
|
||||||
|
|
||||||
lvconvert --regionsize RegionSize LV_raid
|
lvconvert --regionsize RegionSize LV_raid
|
||||||
OO: OO_LVCONVERT
|
OO: OO_LVCONVERT
|
||||||
ID: lvconvert_change_region_size
|
ID: lvconvert_change_region_size
|
||||||
@@ -359,6 +395,13 @@ DESC: Change the region size of an LV.
|
|||||||
RULE: all not lv_is_locked lv_is_pvmove
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
RULE: all not LV_raid0
|
RULE: all not LV_raid0
|
||||||
|
|
||||||
|
lvconvert LV_mirror_raid
|
||||||
|
OO: OO_LVCONVERT
|
||||||
|
ID: lvconvert_raid_types
|
||||||
|
DESC: Remove out-of-place reshape space
|
||||||
|
RULE: all not lv_is_locked lv_is_pvmove
|
||||||
|
RULE: all not LV_raid0 LV_raid1
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# lvconvert raid-related utilities
|
# lvconvert raid-related utilities
|
||||||
|
|||||||
307
tools/command.c
307
tools/command.c
@@ -176,8 +176,8 @@ struct opt_name {
|
|||||||
char _padding[7];
|
char _padding[7];
|
||||||
const char *long_opt; /* --foo */
|
const char *long_opt; /* --foo */
|
||||||
int val_enum; /* xyz_VAL when --foo takes a val like "--foo xyz" */
|
int val_enum; /* xyz_VAL when --foo takes a val like "--foo xyz" */
|
||||||
uint32_t flags;
|
uint32_t unused1;
|
||||||
uint32_t prio;
|
uint32_t unused2;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1229,7 +1229,7 @@ static int is_lvm_all_opt(int opt)
|
|||||||
|
|
||||||
/* Find common options for all variants of each command name. */
|
/* Find common options for all variants of each command name. */
|
||||||
|
|
||||||
void factor_common_options(void)
|
static void factor_common_options(void)
|
||||||
{
|
{
|
||||||
int cn, opt_enum, ci, oo, ro, found;
|
int cn, opt_enum, ci, oo, ro, found;
|
||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
@@ -1506,7 +1506,12 @@ int define_commands(char *run_name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
include_optional_opt_args(&lvm_all, "OO_ALL");
|
/*
|
||||||
|
* For usage.
|
||||||
|
* Predefined string of options common to all commands
|
||||||
|
* (for compact output)
|
||||||
|
*/
|
||||||
|
include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1597,7 +1602,7 @@ static void print_usage_def(struct arg_def *def)
|
|||||||
printf(" ...");
|
printf(" ...");
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_usage(struct command *cmd, int longhelp)
|
void print_usage(struct command *cmd)
|
||||||
{
|
{
|
||||||
struct command_name *cname = find_command_name(cmd->name);
|
struct command_name *cname = find_command_name(cmd->name);
|
||||||
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
|
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
|
||||||
@@ -1647,49 +1652,43 @@ void print_usage(struct command *cmd, int longhelp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!longhelp)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (!cmd->oo_count)
|
if (!cmd->oo_count)
|
||||||
goto op_count;
|
goto op_count;
|
||||||
|
|
||||||
if (cmd->oo_count) {
|
if (cmd->oo_count) {
|
||||||
|
first = 1;
|
||||||
|
|
||||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||||
opt_enum = cmd->optional_opt_args[oo].opt;
|
opt_enum = cmd->optional_opt_args[oo].opt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip common lvm options in lvm_all which
|
* Skip common opts in lvm_all and cname->common_options.
|
||||||
* are printed at the end under "Common options for lvm"
|
|
||||||
* see print_common_options_lvm()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (is_lvm_all_opt(opt_enum))
|
if (is_lvm_all_opt(opt_enum))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* When there is more than one variant,
|
|
||||||
* skip common command options from
|
|
||||||
* cname->common_options (options common
|
|
||||||
* to all variants), which are printed at
|
|
||||||
* the end under "Common options for command"
|
|
||||||
* see print_common_options_cmd()
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((cname->variants > 1) && cname->common_options[opt_enum])
|
if ((cname->variants > 1) && cname->common_options[opt_enum])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printf("\n\t[");
|
if (first)
|
||||||
|
printf("\n\t[");
|
||||||
|
else
|
||||||
|
printf("\n\t ");
|
||||||
|
first = 0;
|
||||||
|
|
||||||
printf(" %s", opt_names[opt_enum].long_opt);
|
printf(" %s", opt_names[opt_enum].long_opt);
|
||||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
print_usage_def(&cmd->optional_opt_args[oo].def);
|
print_usage_def(&cmd->optional_opt_args[oo].def);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" ]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n\t[ COMMON_OPTIONS ]");
|
if (first)
|
||||||
|
printf("\n\t[");
|
||||||
|
else
|
||||||
|
printf("\n\t ");
|
||||||
|
printf(" COMMON_OPTIONS ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
op_count:
|
op_count:
|
||||||
@@ -1714,31 +1713,11 @@ void print_usage(struct command *cmd, int longhelp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_usage_common_lvm(struct command_name *cname, struct command *cmd)
|
void print_usage_common(struct command_name *cname, struct command *cmd)
|
||||||
{
|
{
|
||||||
int oo, opt_enum;
|
int oo, opt_enum, first = 1;
|
||||||
|
|
||||||
printf(" Common options for lvm:");
|
printf(" Common options:");
|
||||||
|
|
||||||
for (oo = 0; oo < lvm_all.oo_count; oo++) {
|
|
||||||
opt_enum = lvm_all.optional_opt_args[oo].opt;
|
|
||||||
|
|
||||||
printf("\n\t[");
|
|
||||||
|
|
||||||
printf(" %s", opt_names[opt_enum].long_opt);
|
|
||||||
if (lvm_all.optional_opt_args[oo].def.val_bits) {
|
|
||||||
printf(" ");
|
|
||||||
print_usage_def(&lvm_all.optional_opt_args[oo].def);
|
|
||||||
}
|
|
||||||
printf(" ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_usage_common_cmd(struct command_name *cname, struct command *cmd)
|
|
||||||
{
|
|
||||||
int oo, opt_enum;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* when there's more than one variant, options that
|
* when there's more than one variant, options that
|
||||||
@@ -1746,9 +1725,7 @@ void print_usage_common_cmd(struct command_name *cname, struct command *cmd)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (cname->variants < 2)
|
if (cname->variants < 2)
|
||||||
return;
|
goto all;
|
||||||
|
|
||||||
printf(" Common options for command:");
|
|
||||||
|
|
||||||
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
||||||
if (!cname->common_options[opt_enum])
|
if (!cname->common_options[opt_enum])
|
||||||
@@ -1757,7 +1734,11 @@ void print_usage_common_cmd(struct command_name *cname, struct command *cmd)
|
|||||||
if (is_lvm_all_opt(opt_enum))
|
if (is_lvm_all_opt(opt_enum))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printf("\n\t[");
|
if (first)
|
||||||
|
printf("\n\t[");
|
||||||
|
else
|
||||||
|
printf("\n\t ");
|
||||||
|
first = 0;
|
||||||
|
|
||||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
||||||
@@ -1770,9 +1751,28 @@ void print_usage_common_cmd(struct command_name *cname, struct command *cmd)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf(" ]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
all:
|
||||||
|
/* options that are common to all lvm commands */
|
||||||
|
|
||||||
|
for (oo = 0; oo < lvm_all.oo_count; oo++) {
|
||||||
|
opt_enum = lvm_all.optional_opt_args[oo].opt;
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
printf("\n\t[");
|
||||||
|
else
|
||||||
|
printf("\n\t ");
|
||||||
|
first = 0;
|
||||||
|
|
||||||
|
printf(" %s", opt_names[opt_enum].long_opt);
|
||||||
|
if (lvm_all.optional_opt_args[oo].def.val_bits) {
|
||||||
|
printf(" ");
|
||||||
|
print_usage_def(&lvm_all.optional_opt_args[oo].def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" ]");
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1785,42 +1785,16 @@ static void print_val_man(const char *str)
|
|||||||
int line_argc;
|
int line_argc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
if (!strcmp(str, "Number") ||
|
||||||
* Doing bold k before underlined Unit creates a lot of
|
!strcmp(str, "String") ||
|
||||||
* visual "noise" that makes the text hard to read.
|
!strncmp(str, "VG", 2) ||
|
||||||
* The extra markup in this case doesn't add anything
|
!strncmp(str, "LV", 2) ||
|
||||||
* that isn't already obvious.
|
!strncmp(str, "PV", 2) ||
|
||||||
*/
|
!strcmp(str, "Tag")) {
|
||||||
|
printf("\\fI%s\\fP", str);
|
||||||
if (!strcmp(str, "Number[k|Unit]")) {
|
|
||||||
printf("\\fINumber\\fP[k|\\fIUnit\\fP]");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(str, "Number[m|Unit]")) {
|
|
||||||
printf("\\fINumber\\fP[m|\\fIUnit\\fP]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(str, "[+|-]Number")) {
|
|
||||||
printf("[\\fB+\\fP|\\fB-\\fP]\\fINumber\\fP");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(str, "[+|-]Number[%VG|%PVS|%FREE]")) {
|
|
||||||
printf("[\\fB+\\fP|\\fB-\\fP]\\fINumber\\fP[\\fB%%VG\\fP|\\fB%%PVS\\fP|\\fB%%FREE\\fP]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(str, "PV[:t|n|y]")) {
|
|
||||||
printf("\\fIPV\\fP[\\fB:t\\fP|\\fBn\\fP|\\fBy\\fP]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* I think this bit is almost unnecessary with the specific
|
|
||||||
* ones checked above.
|
|
||||||
*/
|
|
||||||
if (strstr(str, "Number[") || strstr(str, "]Number")) {
|
if (strstr(str, "Number[") || strstr(str, "]Number")) {
|
||||||
for (i = 0; i < strlen(str); i++) {
|
for (i = 0; i < strlen(str); i++) {
|
||||||
if (str[i] == 'N')
|
if (str[i] == 'N')
|
||||||
@@ -1835,16 +1809,6 @@ static void print_val_man(const char *str)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(str, "Number") ||
|
|
||||||
!strcmp(str, "String") ||
|
|
||||||
!strncmp(str, "VG", 2) ||
|
|
||||||
!strncmp(str, "LV", 2) ||
|
|
||||||
!strncmp(str, "PV", 2) ||
|
|
||||||
!strcmp(str, "Tag")) {
|
|
||||||
printf("\\fI%s\\fP", str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr(str, '|')) {
|
if (strchr(str, '|')) {
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
line = dm_strdup(str);
|
line = dm_strdup(str);
|
||||||
@@ -2149,6 +2113,7 @@ void print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
|
|
||||||
if (cmd->oo_count) {
|
if (cmd->oo_count) {
|
||||||
printf(".RS 4\n");
|
printf(".RS 4\n");
|
||||||
|
printf("[");
|
||||||
|
|
||||||
/* print optional options with short opts */
|
/* print optional options with short opts */
|
||||||
|
|
||||||
@@ -2166,9 +2131,10 @@ void print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
|
|
||||||
if (sep) {
|
if (sep) {
|
||||||
printf("\n.br\n");
|
printf("\n.br\n");
|
||||||
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[ \\fB-%c\\fP|\\fB%s\\fP",
|
printf(" \\fB-%c\\fP|\\fB%s\\fP",
|
||||||
opt_names[opt_enum].short_opt,
|
opt_names[opt_enum].short_opt,
|
||||||
man_long_opt_name(cmd->name, opt_enum));
|
man_long_opt_name(cmd->name, opt_enum));
|
||||||
|
|
||||||
@@ -2176,7 +2142,6 @@ void print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
printf(" ");
|
printf(" ");
|
||||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
||||||
}
|
}
|
||||||
printf(" ]");
|
|
||||||
sep = 1;
|
sep = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2196,10 +2161,11 @@ void print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
|
|
||||||
if (sep) {
|
if (sep) {
|
||||||
printf("\n.br\n");
|
printf("\n.br\n");
|
||||||
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* space alignment without short opt */
|
/* space alignment without short opt */
|
||||||
printf("[ ");
|
printf(" ");
|
||||||
|
|
||||||
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
|
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
|
||||||
|
|
||||||
@@ -2207,16 +2173,17 @@ void print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
printf(" ");
|
printf(" ");
|
||||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
||||||
}
|
}
|
||||||
printf(" ]");
|
|
||||||
sep = 1;
|
sep = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sep) {
|
if (sep) {
|
||||||
printf("\n.br\n");
|
printf("\n.br\n");
|
||||||
|
printf(" ");
|
||||||
/* space alignment without short opt */
|
/* space alignment without short opt */
|
||||||
/* printf(" "); */
|
printf(" ");
|
||||||
}
|
}
|
||||||
printf("[ COMMON_OPTIONS ]\n");
|
printf(" COMMON_OPTIONS");
|
||||||
|
printf(" ]\n");
|
||||||
printf(".RE\n");
|
printf(".RE\n");
|
||||||
printf(".br\n");
|
printf(".br\n");
|
||||||
}
|
}
|
||||||
@@ -2261,7 +2228,7 @@ void print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
* then options with only long names, alphabetically
|
* then options with only long names, alphabetically
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void print_man_usage_common_lvm(struct command *cmd)
|
void print_man_usage_common(struct command *cmd)
|
||||||
{
|
{
|
||||||
struct command_name *cname;
|
struct command_name *cname;
|
||||||
int i, sep, rp, oo, op, opt_enum;
|
int i, sep, rp, oo, op, opt_enum;
|
||||||
@@ -2269,100 +2236,10 @@ void print_man_usage_common_lvm(struct command *cmd)
|
|||||||
if (!(cname = find_command_name(cmd->name)))
|
if (!(cname = find_command_name(cmd->name)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("Common options for lvm:\n");
|
|
||||||
printf(".\n");
|
|
||||||
|
|
||||||
sep = 0;
|
|
||||||
|
|
||||||
printf(".RS 4\n");
|
|
||||||
|
|
||||||
/* print those with short opts */
|
|
||||||
for (i = 0; i < ARG_COUNT; i++) {
|
|
||||||
opt_enum = opt_names_alpha[i]->opt_enum;
|
|
||||||
|
|
||||||
if (!opt_names[opt_enum].short_opt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!is_lvm_all_opt(opt_enum))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (sep) {
|
|
||||||
printf("\n.br\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
|
||||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
printf("[ \\fB-%c\\fP|\\fB%s\\fP",
|
|
||||||
opt_names[opt_enum].short_opt,
|
|
||||||
man_long_opt_name(cmd->name, opt_enum));
|
|
||||||
|
|
||||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
|
||||||
printf(" ");
|
|
||||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
|
||||||
}
|
|
||||||
printf(" ]");
|
|
||||||
sep = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print those without short opts */
|
|
||||||
for (i = 0; i < ARG_COUNT; i++) {
|
|
||||||
opt_enum = opt_names_alpha[i]->opt_enum;
|
|
||||||
|
|
||||||
if (opt_names[opt_enum].short_opt)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!is_lvm_all_opt(opt_enum))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (sep) {
|
|
||||||
printf("\n.br\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
|
||||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* space alignment without short opt */
|
|
||||||
printf("[ ");
|
|
||||||
|
|
||||||
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
|
|
||||||
|
|
||||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
|
||||||
printf(" ");
|
|
||||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
|
||||||
}
|
|
||||||
printf(" ]");
|
|
||||||
sep = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n.RE\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_man_usage_common_cmd(struct command *cmd)
|
|
||||||
{
|
|
||||||
struct command_name *cname;
|
|
||||||
int i, sep, rp, oo, op, opt_enum;
|
|
||||||
|
|
||||||
if (!(cname = find_command_name(cmd->name)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (cname->variants < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
printf("Common options for command:\n");
|
|
||||||
printf(".\n");
|
|
||||||
|
|
||||||
sep = 0;
|
sep = 0;
|
||||||
|
|
||||||
printf(".RS 4\n");
|
printf(".RS 4\n");
|
||||||
|
printf("[");
|
||||||
|
|
||||||
/* print those with short opts */
|
/* print those with short opts */
|
||||||
for (i = 0; i < ARG_COUNT; i++) {
|
for (i = 0; i < ARG_COUNT; i++) {
|
||||||
@@ -2374,22 +2251,19 @@ void print_man_usage_common_cmd(struct command *cmd)
|
|||||||
if (!opt_names[opt_enum].short_opt)
|
if (!opt_names[opt_enum].short_opt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* common cmd options only used with variants */
|
if ((cname->variants < 2) && !is_lvm_all_opt(opt_enum))
|
||||||
if (cname->variants < 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (is_lvm_all_opt(opt_enum))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sep) {
|
if (sep) {
|
||||||
printf("\n.br\n");
|
printf("\n.br\n");
|
||||||
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printf("[ \\fB-%c\\fP|\\fB%s\\fP",
|
printf(" \\fB-%c\\fP|\\fB%s\\fP",
|
||||||
opt_names[opt_enum].short_opt,
|
opt_names[opt_enum].short_opt,
|
||||||
man_long_opt_name(cmd->name, opt_enum));
|
man_long_opt_name(cmd->name, opt_enum));
|
||||||
|
|
||||||
@@ -2397,7 +2271,6 @@ void print_man_usage_common_cmd(struct command *cmd)
|
|||||||
printf(" ");
|
printf(" ");
|
||||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
||||||
}
|
}
|
||||||
printf(" ]");
|
|
||||||
sep = 1;
|
sep = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2414,15 +2287,12 @@ void print_man_usage_common_cmd(struct command *cmd)
|
|||||||
if (opt_names[opt_enum].short_opt)
|
if (opt_names[opt_enum].short_opt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* common cmd options only used with variants */
|
if ((cname->variants < 2) && !is_lvm_all_opt(opt_enum))
|
||||||
if (cname->variants < 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (is_lvm_all_opt(opt_enum))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sep) {
|
if (sep) {
|
||||||
printf("\n.br\n");
|
printf("\n.br\n");
|
||||||
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||||
@@ -2430,7 +2300,7 @@ void print_man_usage_common_cmd(struct command *cmd)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* space alignment without short opt */
|
/* space alignment without short opt */
|
||||||
printf("[ ");
|
printf(" ");
|
||||||
|
|
||||||
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
|
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
|
||||||
|
|
||||||
@@ -2438,15 +2308,12 @@ void print_man_usage_common_cmd(struct command *cmd)
|
|||||||
printf(" ");
|
printf(" ");
|
||||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
||||||
}
|
}
|
||||||
printf(" ]");
|
|
||||||
sep = 1;
|
sep = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n.RE\n");
|
printf(" ]\n");
|
||||||
printf(".br\n");
|
|
||||||
printf("\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2616,6 +2483,7 @@ void print_man_all_options_list(struct command_name *cname)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* All options used for a given command name, along with descriptions.
|
* All options used for a given command name, along with descriptions.
|
||||||
|
* listed in order of:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void print_man_all_options_desc(struct command_name *cname)
|
void print_man_all_options_desc(struct command_name *cname)
|
||||||
@@ -2654,9 +2522,6 @@ void print_man_all_options_desc(struct command_name *cname)
|
|||||||
print_val_man(val_names[val_enum].usage);
|
print_val_man(val_names[val_enum].usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_names[opt_enum].flags & ARG_COUNTABLE)
|
|
||||||
printf(" ...");
|
|
||||||
|
|
||||||
if (opt_names[opt_enum].desc) {
|
if (opt_names[opt_enum].desc) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(".br\n");
|
printf(".br\n");
|
||||||
@@ -2798,13 +2663,13 @@ void print_man_all_positions_desc(struct command_name *cname)
|
|||||||
/* Nearly every command uses a number arg somewhere. */
|
/* Nearly every command uses a number arg somewhere. */
|
||||||
|
|
||||||
printf("\n.HP\n");
|
printf("\n.HP\n");
|
||||||
printf("\\fINumber\\fP, \\fIUnit\\fP");
|
printf("\\fINumber\\fP, \\fISize\\fP");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(".br\n");
|
printf(".br\n");
|
||||||
printf("Input units are always treated as base two values, regardless of unit\n"
|
printf("Input units are always treated as base two values, regardless of unit\n"
|
||||||
"capitalization, e.g. 'k' and 'K' both refer to 1024.\n"
|
"capitalization, e.g. 'k' and 'K' both refer to 1024.\n"
|
||||||
"The default input unit is specified by letter, followed by |\\fIUnit\\fP\n"
|
"The default input unit is specified by letter, followed by |unit which\n"
|
||||||
"which represents other possible input units: \\fBbBsSkKmMgGtTpPeE\\fP.\n");
|
"represents other possible input units: bBsSkKmMgGtTpPeE.\n");
|
||||||
|
|
||||||
printf("\n.HP\n");
|
printf("\n.HP\n");
|
||||||
printf("Environment");
|
printf("Environment");
|
||||||
@@ -2911,8 +2776,9 @@ void print_man(char *name, char *des_file, int include_primary, int include_seco
|
|||||||
cmd = &commands[i];
|
cmd = &commands[i];
|
||||||
|
|
||||||
if (prev_cmd && strcmp(prev_cmd->name, cmd->name)) {
|
if (prev_cmd && strcmp(prev_cmd->name, cmd->name)) {
|
||||||
print_man_usage_common_cmd(prev_cmd);
|
printf("Common options:\n");
|
||||||
print_man_usage_common_lvm(prev_cmd);
|
printf(".\n");
|
||||||
|
print_man_usage_common(prev_cmd);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(".SH OPTIONS\n");
|
printf(".SH OPTIONS\n");
|
||||||
@@ -3008,8 +2874,9 @@ void print_man(char *name, char *des_file, int include_primary, int include_seco
|
|||||||
print_man_usage(lvmname, cmd);
|
print_man_usage(lvmname, cmd);
|
||||||
|
|
||||||
if (i == (COMMAND_COUNT - 1)) {
|
if (i == (COMMAND_COUNT - 1)) {
|
||||||
print_man_usage_common_cmd(cmd);
|
printf("Common options:\n");
|
||||||
print_man_usage_common_lvm(cmd);
|
printf(".\n");
|
||||||
|
print_man_usage_common(cmd);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(".SH OPTIONS\n");
|
printf(".SH OPTIONS\n");
|
||||||
|
|||||||
@@ -213,9 +213,7 @@ struct command {
|
|||||||
|
|
||||||
int define_commands(char *run_name);
|
int define_commands(char *run_name);
|
||||||
int command_id_to_enum(const char *str);
|
int command_id_to_enum(const char *str);
|
||||||
void print_usage(struct command *cmd, int longhelp);
|
void print_usage(struct command *cmd);
|
||||||
void print_usage_common_cmd(struct command_name *cname, struct command *cmd);
|
void print_usage_common(struct command_name *cname, struct command *cmd);
|
||||||
void print_usage_common_lvm(struct command_name *cname, struct command *cmd);
|
|
||||||
void factor_common_options(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -740,12 +740,12 @@ static int _lvchange_writemostly(struct logical_volume *lv)
|
|||||||
struct lv_segment *raid_seg = first_seg(lv);
|
struct lv_segment *raid_seg = first_seg(lv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prohibit writebehind and writebehind during synchronization.
|
* Prohibit on synchronization.
|
||||||
*
|
*
|
||||||
* FIXME: we can do better once we can distingush between
|
* FIXME: we can do better once we can distingush between
|
||||||
* an initial sync after a linear -> raid1 upconversion
|
* an initial sync after a linear -> raid1 upconversion
|
||||||
* and any later additions of legs, requested resyncs
|
* and any later additions of legs, requested resyncs
|
||||||
* via lvchange or leg repairs/replacements.
|
* via lvchange or leg repairs/replacements.
|
||||||
*/
|
*/
|
||||||
if (!lv_raid_in_sync(lv)) {
|
if (!lv_raid_in_sync(lv)) {
|
||||||
log_error("Unable to change write%s on %s while it is not in-sync.",
|
log_error("Unable to change write%s on %s while it is not in-sync.",
|
||||||
|
|||||||
@@ -1228,6 +1228,9 @@ static int _lvconvert_mirrors(struct cmd_context *cmd,
|
|||||||
static int _is_valid_raid_conversion(const struct segment_type *from_segtype,
|
static int _is_valid_raid_conversion(const struct segment_type *from_segtype,
|
||||||
const struct segment_type *to_segtype)
|
const struct segment_type *to_segtype)
|
||||||
{
|
{
|
||||||
|
if (!from_segtype)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (from_segtype == to_segtype)
|
if (from_segtype == to_segtype)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -1356,7 +1359,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
|
|||||||
DEFAULT_RAID1_MAX_IMAGES, lp->segtype->name, display_lvname(lv));
|
DEFAULT_RAID1_MAX_IMAGES, lp->segtype->name, display_lvname(lv));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!lv_raid_change_image_count(lv, image_count, lp->pvh))
|
if (!lv_raid_change_image_count(lv, image_count, lp->region_size, lp->pvh))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
log_print_unless_silent("Logical volume %s successfully converted.",
|
log_print_unless_silent("Logical volume %s successfully converted.",
|
||||||
@@ -1365,10 +1368,13 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
goto try_new_takeover_or_reshape;
|
goto try_new_takeover_or_reshape;
|
||||||
} else if (!*lp->type_str || seg->segtype == lp->segtype) {
|
}
|
||||||
|
#if 0
|
||||||
|
} else if ((!*lp->type_str || seg->segtype == lp->segtype) && !lp->stripe_size_supplied) {
|
||||||
log_error("Conversion operation not yet supported.");
|
log_error("Conversion operation not yet supported.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((seg_is_linear(seg) || seg_is_striped(seg) || seg_is_mirrored(seg) || lv_is_raid(lv)) &&
|
if ((seg_is_linear(seg) || seg_is_striped(seg) || seg_is_mirrored(seg) || lv_is_raid(lv)) &&
|
||||||
(lp->type_str && lp->type_str[0])) {
|
(lp->type_str && lp->type_str[0])) {
|
||||||
@@ -1390,10 +1396,14 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME This needs changing globally. */
|
||||||
if (!arg_is_set(cmd, stripes_long_ARG))
|
if (!arg_is_set(cmd, stripes_long_ARG))
|
||||||
lp->stripes = 0;
|
lp->stripes = 0;
|
||||||
|
if (!arg_is_set(cmd, type_ARG))
|
||||||
|
lp->segtype = NULL;
|
||||||
|
|
||||||
if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size,
|
if (!lv_raid_convert(lv, lp->segtype,
|
||||||
|
lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size,
|
||||||
lp->region_size, lp->pvh))
|
lp->region_size, lp->pvh))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -1410,12 +1420,16 @@ try_new_takeover_or_reshape:
|
|||||||
/* FIXME This needs changing globally. */
|
/* FIXME This needs changing globally. */
|
||||||
if (!arg_is_set(cmd, stripes_long_ARG))
|
if (!arg_is_set(cmd, stripes_long_ARG))
|
||||||
lp->stripes = 0;
|
lp->stripes = 0;
|
||||||
|
if (!arg_is_set(cmd, type_ARG))
|
||||||
|
lp->segtype = NULL;
|
||||||
|
|
||||||
/* Only let raid4 through for now. */
|
/* Only let raid4 through for now. */
|
||||||
if (lp->type_str && lp->type_str[0] && lp->segtype != seg->segtype &&
|
if (!lp->segtype ||
|
||||||
((seg_is_raid4(seg) && seg_is_striped(lp) && lp->stripes > 1) ||
|
(lp->type_str && lp->type_str[0] && lp->segtype != seg->segtype &&
|
||||||
(seg_is_striped(seg) && seg->area_count > 1 && seg_is_raid4(lp)))) {
|
((seg_is_raid4(seg) && seg_is_striped(lp) && lp->stripes > 1) ||
|
||||||
if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size,
|
(seg_is_striped(seg) && seg->area_count > 1 && seg_is_raid4(lp))))) {
|
||||||
|
if (!lv_raid_convert(lv, lp->segtype,
|
||||||
|
lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size,
|
||||||
lp->region_size, lp->pvh))
|
lp->region_size, lp->pvh))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -1700,6 +1714,8 @@ static int _lvconvert_raid_types(struct cmd_context *cmd, struct logical_volume
|
|||||||
/* FIXME This is incomplete */
|
/* FIXME This is incomplete */
|
||||||
if (_mirror_or_raid_type_requested(cmd, lp->type_str) || _raid0_type_requested(lp->type_str) ||
|
if (_mirror_or_raid_type_requested(cmd, lp->type_str) || _raid0_type_requested(lp->type_str) ||
|
||||||
_striped_type_requested(lp->type_str) || lp->mirrorlog || lp->corelog) {
|
_striped_type_requested(lp->type_str) || lp->mirrorlog || lp->corelog) {
|
||||||
|
if (!arg_is_set(cmd, type_ARG))
|
||||||
|
lp->segtype = first_seg(lv)->segtype;
|
||||||
/* FIXME Handle +/- adjustments too? */
|
/* FIXME Handle +/- adjustments too? */
|
||||||
if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
|
if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
|
||||||
goto_out;
|
goto_out;
|
||||||
@@ -2990,9 +3006,9 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a new pool segment */
|
/* Allocate a new pool segment */
|
||||||
if (!(seg = alloc_lv_segment(pool_segtype, pool_lv, 0, data_lv->le_count,
|
if (!(seg = alloc_lv_segment(pool_segtype, pool_lv, 0, data_lv->le_count, 0,
|
||||||
pool_lv->status, 0, NULL, 1,
|
pool_lv->status, 0, NULL, 1,
|
||||||
data_lv->le_count, 0, 0, 0, NULL)))
|
data_lv->le_count, 0, 0, 0, 0, NULL)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
/* Add the new segment to the layer LV */
|
/* Add the new segment to the layer LV */
|
||||||
|
|||||||
@@ -1564,7 +1564,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
|
|||||||
log_error("Run '%s --help' for more information.", name);
|
log_error("Run '%s --help' for more information.", name);
|
||||||
if (close_ro) {
|
if (close_ro) {
|
||||||
log_warn("Closest command usage is:");
|
log_warn("Closest command usage is:");
|
||||||
print_usage(&_cmdline.commands[close_i], 0);
|
print_usage(&_cmdline.commands[close_i]);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1677,6 +1677,39 @@ static void _short_usage(const char *name)
|
|||||||
log_error("Run `%s --help' for more information.", name);
|
log_error("Run `%s --help' for more information.", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _usage_notes(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Excluding commonly understood syntax style like the meanings of:
|
||||||
|
* [ ] for optional, ... for repeatable, | for one of the following,
|
||||||
|
* -- for an option name, lower case strings and digits for literals.
|
||||||
|
*/
|
||||||
|
log_print("Usage notes:\n"
|
||||||
|
". Variable parameters are: Number, String, PV, VG, LV, Tag.\n"
|
||||||
|
". Select indicates that a required positional parameter can\n"
|
||||||
|
" be omitted if the --select option is used.\n"
|
||||||
|
". --size Number can be replaced with --extents NumberExtents.\n"
|
||||||
|
". When --name is omitted from lvcreate, a new LV name is\n"
|
||||||
|
" generated with the \"lvol\" prefix and a unique numeric suffix.\n"
|
||||||
|
". The required VG parameter in lvcreate may be omitted when\n"
|
||||||
|
" the VG name is included in another option, e.g. --name VG/LV.\n"
|
||||||
|
". For required options listed in parentheses, e.g. (--A, --B),\n"
|
||||||
|
" any one is required, after which the others are optional.\n"
|
||||||
|
". The _new suffix indicates the VG or LV must not yet exist.\n"
|
||||||
|
". LV followed by _<type> indicates that an LV of the given type\n"
|
||||||
|
" is required. (raid represents any raid<N> type.)\n"
|
||||||
|
". Input units are always treated as base two values, regardless of\n"
|
||||||
|
" unit capitalization, e.g. 'k' and 'K' both refer to 1024.\n"
|
||||||
|
". The default input unit is specified by letter, followed by |unit\n"
|
||||||
|
" which represents other possible input units: bBsSkKmMgGtTpPeE.\n"
|
||||||
|
". Output units can be specified with the --units option, for which\n"
|
||||||
|
" lower/upper case letters refer to base 2/10 values.\n"
|
||||||
|
" formats that are recognized, e.g. for compatibility.\n"
|
||||||
|
". See man pages for short option equivalents of long option names,\n"
|
||||||
|
" and for more detailed descriptions of variable parameters.\n"
|
||||||
|
" \n");
|
||||||
|
}
|
||||||
|
|
||||||
static int _usage(const char *name, int longhelp)
|
static int _usage(const char *name, int longhelp)
|
||||||
{
|
{
|
||||||
struct command_name *cname = find_command_name(name);
|
struct command_name *cname = find_command_name(name);
|
||||||
@@ -1688,19 +1721,8 @@ static int _usage(const char *name, int longhelp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Looks at all variants of each command name and figures out
|
|
||||||
* which options are common to all variants (for compact output)
|
|
||||||
*/
|
|
||||||
factor_common_options();
|
|
||||||
|
|
||||||
log_print("%s - %s\n", name, cname->desc);
|
log_print("%s - %s\n", name, cname->desc);
|
||||||
|
|
||||||
/* Reduce the default output when there are several variants. */
|
|
||||||
|
|
||||||
if (cname->variants < 3)
|
|
||||||
longhelp = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < COMMAND_COUNT; i++) {
|
for (i = 0; i < COMMAND_COUNT; i++) {
|
||||||
if (strcmp(_cmdline.commands[i].name, name))
|
if (strcmp(_cmdline.commands[i].name, name))
|
||||||
continue;
|
continue;
|
||||||
@@ -1711,16 +1733,15 @@ static int _usage(const char *name, int longhelp)
|
|||||||
if ((_cmdline.commands[i].cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !longhelp)
|
if ((_cmdline.commands[i].cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !longhelp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
print_usage(&_cmdline.commands[i], longhelp);
|
print_usage(&_cmdline.commands[i]);
|
||||||
cmd = &_cmdline.commands[i];
|
cmd = &_cmdline.commands[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Common options are printed once for all variants of a command name. */
|
/* Common options are printed once for all variants of a command name. */
|
||||||
if (longhelp) {
|
print_usage_common(cname, cmd);
|
||||||
print_usage_common_cmd(cname, cmd);
|
|
||||||
print_usage_common_lvm(cname, cmd);
|
if (longhelp)
|
||||||
} else
|
_usage_notes();
|
||||||
log_print("Use --longhelp to show all options.");
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1305,6 +1305,7 @@ static int _validate_stripe_params(struct cmd_context *cmd, const struct segment
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printf("%s[%u] *stripe_size=%u\n", __func__, __LINE__, *stripe_size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,6 +1325,7 @@ int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtyp
|
|||||||
*stripes_supplied = arg_is_set(cmd, stripes_long_ARG) ? : arg_is_set(cmd, stripes_ARG);
|
*stripes_supplied = arg_is_set(cmd, stripes_long_ARG) ? : arg_is_set(cmd, stripes_ARG);
|
||||||
|
|
||||||
*stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
|
*stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
|
||||||
|
// printf("%s[%u] *stripe_size=%u\n", __func__, __LINE__, *stripe_size);
|
||||||
*stripe_size_supplied = arg_is_set(cmd, stripesize_ARG);
|
*stripe_size_supplied = arg_is_set(cmd, stripesize_ARG);
|
||||||
if (*stripe_size) {
|
if (*stripe_size) {
|
||||||
if (arg_sign_value(cmd, stripesize_ARG, SIGN_NONE) == SIGN_MINUS) {
|
if (arg_sign_value(cmd, stripesize_ARG, SIGN_NONE) == SIGN_MINUS) {
|
||||||
@@ -1338,6 +1340,7 @@ int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printf("%s[%u] *stripe_size=%u\n", __func__, __LINE__, *stripe_size);
|
||||||
return _validate_stripe_params(cmd, segtype, stripes, stripe_size);
|
return _validate_stripe_params(cmd, segtype, stripes, stripe_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5755,3 +5758,4 @@ bad:
|
|||||||
out:
|
out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
tools/vals.h
12
tools/vals.h
@@ -83,10 +83,10 @@
|
|||||||
* could be "Number[bBsSkKmMgGtTpPeE]" (with implied |),
|
* could be "Number[bBsSkKmMgGtTpPeE]" (with implied |),
|
||||||
* but repeating this full specification produces cluttered
|
* but repeating this full specification produces cluttered
|
||||||
* output, and doesn't indicate which unit is the default.
|
* output, and doesn't indicate which unit is the default.
|
||||||
* "Number[Units]" would be cleaner, as would a subset of
|
* "Number[units]" would be cleaner, as would a subset of
|
||||||
* common units, e.g. "Number[kmg...]", but neither helps
|
* common units, e.g. "Number[kmg...]", but neither helps
|
||||||
* with default. "Number[k|Unit]" and "Number[m|Unit]" show
|
* with default. "Number[k|unit]" and "Number[m|unit]" show
|
||||||
* the default, and "Unit" indicates that other units
|
* the default, and "unit" indicates that other units
|
||||||
* are possible without listing them all. This also
|
* are possible without listing them all. This also
|
||||||
* suggests using the preferred lower case letters, because
|
* suggests using the preferred lower case letters, because
|
||||||
* --size and other option args treat upper/lower letters
|
* --size and other option args treat upper/lower letters
|
||||||
@@ -115,9 +115,9 @@ val(activation_VAL, activation_arg, "Active", "y|n|ay")
|
|||||||
val(cachemode_VAL, cachemode_arg, "CacheMode", "writethrough|writeback")
|
val(cachemode_VAL, cachemode_arg, "CacheMode", "writethrough|writeback")
|
||||||
val(discards_VAL, discards_arg, "Discards", "passdown|nopassdown|ignore")
|
val(discards_VAL, discards_arg, "Discards", "passdown|nopassdown|ignore")
|
||||||
val(mirrorlog_VAL, mirrorlog_arg, "MirrorLog", "core|disk")
|
val(mirrorlog_VAL, mirrorlog_arg, "MirrorLog", "core|disk")
|
||||||
val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|Unit]")
|
val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|unit]")
|
||||||
val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|Unit]")
|
val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|unit]")
|
||||||
val(regionsize_VAL, regionsize_arg, "RegionSize", "Number[m|Unit]")
|
val(regionsize_VAL, regionsize_arg, "RegionSize", "Number[m|unit]")
|
||||||
val(numsigned_VAL, int_arg_with_sign, "SNumber", "[+|-]Number")
|
val(numsigned_VAL, int_arg_with_sign, "SNumber", "[+|-]Number")
|
||||||
val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%VG|%PVS|%FREE]")
|
val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%VG|%PVS|%FREE]")
|
||||||
val(permission_VAL, permission_arg, "Permission", "rw|r")
|
val(permission_VAL, permission_arg, "Permission", "rw|r")
|
||||||
|
|||||||
Reference in New Issue
Block a user