diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c index 8c33a5e52..e58de6620 100644 --- a/lib/metadata/lv.c +++ b/lib/metadata/lv.c @@ -1279,7 +1279,7 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_ if (((lv_is_thin_volume(lv) && (seg = first_seg(lv)) && seg->pool_lv && (seg = first_seg(seg->pool_lv))) || (lv_is_thin_pool(lv) && (seg = first_seg(lv)))) && - seg->zero_new_blocks) + (seg->zero_new_blocks == THIN_ZERO_YES)) repstr[7] = 'z'; else repstr[7] = '-'; diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 90c61aa49..cb9ba68d0 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -7684,7 +7684,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, first_seg(lv)->max_recovery_rate = lp->max_recovery_rate; } else if (lv_is_thin_pool(lv)) { first_seg(lv)->chunk_size = lp->chunk_size; - first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0; + first_seg(lv)->zero_new_blocks = lp->zero_new_blocks; first_seg(lv)->discards = lp->discards; if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->passed_args, lp->thin_chunk_size_calc_policy)) { diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c index b600bc409..a5cb9f3ce 100644 --- a/lib/metadata/merge.c +++ b/lib/metadata/merge.c @@ -396,10 +396,14 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg, if (!validate_thin_pool_chunk_size(lv->vg->cmd, seg->chunk_size)) seg_error("has invalid chunk size."); + + if (seg->zero_new_blocks != THIN_ZERO_YES && + seg->zero_new_blocks != THIN_ZERO_NO) + seg_error("zero_new_blocks is invalid"); } else { /* !thin_pool */ - if (seg->zero_new_blocks) + if (seg->zero_new_blocks != THIN_ZERO_UNSELECTED) seg_error("sets zero_new_blocks"); - if (seg->discards) + if (seg->discards != THIN_DISCARDS_UNSELECTED) seg_error("sets discards"); if (!dm_list_empty(&seg->thin_messages)) seg_error("sets thin_messages list"); diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index c80a3c579..42ca82041 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -275,6 +275,13 @@ enum { }; typedef enum { + THIN_ZERO_UNSELECTED = 0, + THIN_ZERO_NO, + THIN_ZERO_YES, +} thin_zero_t; + +typedef enum { + THIN_DISCARDS_UNSELECTED = 0, THIN_DISCARDS_IGNORE, THIN_DISCARDS_NO_PASSDOWN, THIN_DISCARDS_PASSDOWN, @@ -482,7 +489,7 @@ struct lv_segment { struct lv_segment_area *meta_areas; /* For RAID */ struct logical_volume *metadata_lv; /* For thin_pool */ uint64_t transaction_id; /* For thin_pool, thin */ - unsigned zero_new_blocks; /* For thin_pool */ + thin_zero_t zero_new_blocks; /* For thin_pool */ thin_discards_t discards; /* For thin_pool */ struct dm_list thin_messages; /* For thin_pool */ struct logical_volume *external_lv; /* For thin */ @@ -868,7 +875,7 @@ int update_thin_pool_params(const struct segment_type *segtype, int passed_args, uint32_t pool_data_extents, uint32_t *pool_metadata_extents, int *chunk_size_calc_method, uint32_t *chunk_size, - thin_discards_t *discards, int *zero); + thin_discards_t *discards, thin_zero_t *zero_new_blocks); const char *get_pool_discards_name(thin_discards_t discards); int set_pool_discards(thin_discards_t *discards, const char *str); struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv, @@ -931,6 +938,7 @@ struct lvcreate_params { int activation_skip; /* activation skip flags */ activation_change_t activate; /* non-snapshot, non-mirror */ thin_discards_t discards; /* thin */ + thin_zero_t zero_new_blocks; #define THIN_CHUNK_SIZE_CALC_METHOD_GENERIC 0x01 #define THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE 0x02 int thin_chunk_size_calc_policy; diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c index 7748cd3dd..5c74248bd 100644 --- a/lib/metadata/thin_manip.c +++ b/lib/metadata/thin_manip.c @@ -604,7 +604,7 @@ int update_thin_pool_params(const struct segment_type *segtype, uint32_t pool_data_extents, uint32_t *pool_metadata_extents, int *chunk_size_calc_method, uint32_t *chunk_size, - thin_discards_t *discards, int *zero) + thin_discards_t *discards, thin_zero_t *zero_new_blocks) { struct cmd_context *cmd = vg->cmd; struct profile *profile = vg->profile; @@ -625,7 +625,9 @@ int update_thin_pool_params(const struct segment_type *segtype, if (!validate_thin_pool_chunk_size(cmd, *chunk_size)) return_0; - if (!(passed_args & PASS_ARG_DISCARDS)) { + if (discards && + (*discards == THIN_DISCARDS_UNSELECTED) && + find_config_tree_node(cmd, allocation_thin_pool_discards_CFG, profile)) { if (!(str = find_config_tree_str(cmd, allocation_thin_pool_discards_CFG, profile))) { log_error(INTERNAL_ERROR "Could not find configuration."); return 0; @@ -634,8 +636,11 @@ int update_thin_pool_params(const struct segment_type *segtype, return_0; } - if (!(passed_args & PASS_ARG_ZERO)) - *zero = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile); + if (zero_new_blocks && + (*zero_new_blocks == THIN_ZERO_UNSELECTED) && + find_config_tree_node(cmd, allocation_thin_pool_zero_CFG, profile)) + *zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile) + ? THIN_ZERO_YES : THIN_ZERO_NO; if (!(attr & THIN_FEATURE_BLOCK_SIZE) && !is_power_of_2(*chunk_size)) { @@ -705,6 +710,13 @@ int update_thin_pool_params(const struct segment_type *segtype, extents_from_size(vg->cmd, pool_metadata_size, extent_size))) return_0; + if (discards && (*discards == THIN_DISCARDS_UNSELECTED)) + if (!set_pool_discards(discards, DEFAULT_THIN_POOL_DISCARDS)) + return_0; + + if (zero_new_blocks && (*zero_new_blocks == THIN_ZERO_UNSELECTED)) + *zero_new_blocks = (DEFAULT_THIN_POOL_ZERO) ? THIN_ZERO_YES : THIN_ZERO_NO; + return 1; } @@ -733,11 +745,10 @@ const char *get_pool_discards_name(thin_discards_t discards) return "nopassdown"; case THIN_DISCARDS_IGNORE: return "ignore"; + default: + log_error(INTERNAL_ERROR "Unknown discards type encountered."); + return "unknown"; } - - log_error(INTERNAL_ERROR "Unknown discards type encountered."); - - return "unknown"; } int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count) diff --git a/lib/report/properties.c b/lib/report/properties.c index 04f2cef24..c07fb2a42 100644 --- a/lib/report/properties.c +++ b/lib/report/properties.c @@ -470,7 +470,7 @@ GET_LVSEG_NUM_PROPERTY_FN(chunk_size, (SECTOR_SIZE * lvseg_chunksize(lvseg))) #define _chunk_size_set prop_not_implemented_set GET_LVSEG_NUM_PROPERTY_FN(thin_count, dm_list_size(&lvseg->lv->segs_using_this_lv)) #define _thin_count_set prop_not_implemented_set -GET_LVSEG_NUM_PROPERTY_FN(zero, lvseg->zero_new_blocks) +GET_LVSEG_NUM_PROPERTY_FN(zero, (lvseg->zero_new_blocks == THIN_ZERO_YES)) #define _zero_set prop_not_implemented_set GET_LVSEG_NUM_PROPERTY_FN(transaction_id, lvseg->transaction_id) #define _transaction_id_set prop_not_implemented_set diff --git a/lib/report/report.c b/lib/report/report.c index b5791c608..27269d4a9 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -3654,7 +3654,7 @@ static int _thinzero_disp(struct dm_report *rh, struct dm_pool *mem, seg = first_seg(seg->pool_lv); if (seg_is_thin_pool(seg)) - return _binary_disp(rh, mem, field, seg->zero_new_blocks, GET_FIRST_RESERVED_NAME(zero_y), private); + return _binary_disp(rh, mem, field, (seg->zero_new_blocks == THIN_ZERO_YES), GET_FIRST_RESERVED_NAME(zero_y), private); return _binary_undef_disp(rh, mem, field, private); } diff --git a/lib/thin/thin.c b/lib/thin/thin.c index 1e295663d..73fffa67f 100644 --- a/lib/thin/thin.c +++ b/lib/thin/thin.c @@ -45,7 +45,7 @@ static void _thin_pool_display(const struct lv_segment *seg) dm_list_size(&seg->lv->segs_using_this_lv)); log_print(" Transaction ID\t%" PRIu64, seg->transaction_id); log_print(" Zero new blocks\t%s", - seg->zero_new_blocks ? "yes" : "no"); + (seg->zero_new_blocks == THIN_ZERO_YES) ? "yes" : "no"); log_print(" "); } @@ -84,6 +84,7 @@ static int _thin_pool_text_import(struct lv_segment *seg, const char *lv_name; struct logical_volume *pool_data_lv, *pool_metadata_lv; const char *discards_str = NULL; + uint32_t zero = 0; if (!dm_config_get_str(sn, "metadata", &lv_name)) return SEG_LOG_ERROR("Metadata must be a string in"); @@ -124,9 +125,11 @@ static int _thin_pool_text_import(struct lv_segment *seg, seg->device_id); if (dm_config_has_node(sn, "zero_new_blocks") && - !dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) + !dm_config_get_uint32(sn, "zero_new_blocks", &zero)) return SEG_LOG_ERROR("Could not read zero_new_blocks for"); + seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO; + /* Read messages */ for (; sn; sn = sn->sib) if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child)) @@ -165,8 +168,13 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter return 0; } - if (seg->zero_new_blocks) + if (seg->zero_new_blocks == THIN_ZERO_YES) outf(f, "zero_new_blocks = 1"); + else if (seg->zero_new_blocks != THIN_ZERO_NO) { + log_error(INTERNAL_ERROR "Invalid zero new blocks value %d.", + seg->zero_new_blocks); + return 0; + } dm_list_iterate_items(tmsg, &seg->thin_messages) { /* Extra validation */ @@ -304,7 +312,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm, seg->transaction_id, metadata_dlid, pool_dlid, seg->chunk_size, low_water_mark, - seg->zero_new_blocks ? 0 : 1)) + (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1)) return_0; if (attr & THIN_FEATURE_DISCARDS) { diff --git a/tools/lvchange.c b/tools/lvchange.c index cba0496f3..8fae806cb 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -98,7 +98,7 @@ static int _lvchange_pool_update(struct cmd_context *cmd, } if (arg_is_set(cmd, zero_ARG)) { - val = arg_uint_value(cmd, zero_ARG, 1); + val = arg_uint_value(cmd, zero_ARG, 0) ? THIN_ZERO_YES : THIN_ZERO_NO; if (val != first_seg(lv)->zero_new_blocks) { first_seg(lv)->zero_new_blocks = val; update++; diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 3d7259e4e..4ed501849 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -3063,9 +3063,9 @@ static int _lvconvert_to_pool(struct cmd_context *cmd, const char *discards_name; if (arg_is_set(cmd, zero_ARG)) - seg->zero_new_blocks = arg_int_value(cmd, zero_ARG, 0); + seg->zero_new_blocks = arg_int_value(cmd, zero_ARG, 0) ? THIN_ZERO_YES : THIN_ZERO_NO; else - seg->zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, vg->profile); + seg->zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, vg->profile) ? THIN_ZERO_YES : THIN_ZERO_NO; if (arg_is_set(cmd, discards_ARG)) seg->discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_PASSDOWN); @@ -3097,7 +3097,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd, if (!vg_write(vg) || !vg_commit(vg)) return_0; - if (seg->zero_new_blocks && + if ((seg->zero_new_blocks == THIN_ZERO_YES) && seg->chunk_size >= DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE * 2) log_warn("WARNING: Pool zeroing and large %s chunk size slows down provisioning.", display_size(cmd, seg->chunk_size)); diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 206a10b62..63b2c6dce 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -1079,7 +1079,7 @@ static int _lvcreate_params(struct cmd_context *cmd, (lp->create_pool && !get_pool_params(cmd, lp->segtype, &lp->passed_args, &lp->pool_metadata_size, &lp->pool_metadata_spare, - &lp->chunk_size, &lp->discards, &lp->zero)) || + &lp->chunk_size, &lp->discards, &lp->zero_new_blocks)) || !_read_cache_params(cmd, lp) || !_read_mirror_and_raid_params(cmd, lp)) return_0; diff --git a/tools/toollib.c b/tools/toollib.c index c10f5ca4f..c9461e5bd 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -1199,22 +1199,26 @@ int get_pool_params(struct cmd_context *cmd, int *pool_metadata_spare, uint32_t *chunk_size, thin_discards_t *discards, - int *zero) + thin_zero_t *zero_new_blocks) { *passed_args = 0; if (segtype_is_thin_pool(segtype) || segtype_is_thin(segtype)) { if (arg_is_set(cmd, zero_ARG)) { *passed_args |= PASS_ARG_ZERO; - *zero = arg_int_value(cmd, zero_ARG, 1); - log_very_verbose("%s pool zeroing.", *zero ? "Enabling" : "Disabling"); - } + *zero_new_blocks = arg_int_value(cmd, zero_ARG, 0) ? THIN_ZERO_YES : THIN_ZERO_NO; + log_very_verbose("%s pool zeroing.", + (*zero_new_blocks == THIN_ZERO_YES) ? "Enabling" : "Disabling"); + } else + *zero_new_blocks = THIN_ZERO_UNSELECTED; + if (arg_is_set(cmd, discards_ARG)) { *passed_args |= PASS_ARG_DISCARDS; *discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, 0); log_very_verbose("Setting pool discards to %s.", get_pool_discards_name(*discards)); - } + } else + *discards = THIN_DISCARDS_UNSELECTED; } if (arg_from_list_is_negative(cmd, "may not be negative", diff --git a/tools/toollib.h b/tools/toollib.h index 504721e86..7c588fce4 100644 --- a/tools/toollib.h +++ b/tools/toollib.h @@ -214,7 +214,7 @@ int get_pool_params(struct cmd_context *cmd, int *pool_metadata_spare, uint32_t *chunk_size, thin_discards_t *discards, - int *zero); + thin_zero_t *zero_new_blocks); int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t *stripes, uint32_t *stripe_size,