return (lv->status & LV_ACTIVATION_SKIP) ? 1 : 0;
}
+/* Greatest common divisor */
+static unsigned long _gcd(unsigned long n1, unsigned long n2)
+{
+ unsigned long remainder;
+
+ do {
+ remainder = n1 % n2;
+ n1 = n2;
+ n2 = remainder;
+ } while (n2);
+
+ return n1;
+}
+
+/* Least common multiple */
+static unsigned long _lcm(unsigned long n1, unsigned long n2)
+{
+ if (!n1 || !n2)
+ return 0;
+ return (n1 * n2) / _gcd(n1, n2);
+}
+
+static int _recalculate_thin_pool_chunk_size_with_dev_hints(struct lvcreate_params *lp,
+ struct logical_volume *pool_lv)
+{
+ struct logical_volume *pool_data_lv;
+ struct lv_segment *seg;
+ struct physical_volume *pv;
+ struct cmd_context *cmd = pool_lv->vg->cmd;
+ unsigned long previous_hint = 0, hint;
+ uint32_t chunk_size = lp->chunk_size;
+ uint32_t default_chunk_size = lp->thin_chunk_size_calc_method == THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE ?
+ DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE*2 : DEFAULT_THIN_POOL_CHUNK_SIZE*2;
+
+ if (lp->passed_args & PASS_ARG_CHUNK_SIZE ||
+ find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, NULL))
+ goto out;
+
+ pool_data_lv = seg_lv(first_seg(pool_lv), 0);
+
+ dm_list_iterate_items(seg, &pool_data_lv->segments) {
+ pv = seg_pv(seg, 0);
+ if (lp->thin_chunk_size_calc_method == THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE)
+ hint = dev_optimal_io_size(cmd->dev_types, pv_dev(pv));
+ else
+ hint = dev_minimum_io_size(cmd->dev_types, pv_dev(pv));
+
+ if (!hint)
+ continue;
+ if (previous_hint)
+ hint = _lcm(previous_hint, hint);
+ previous_hint = hint;
+ }
+
+ if (hint < DM_THIN_MIN_DATA_BLOCK_SIZE ||
+ hint > DM_THIN_MAX_DATA_BLOCK_SIZE) {
+ log_debug_alloc("Calculated value of %ld sectors for thin pool "
+ "chunk size is out of allowed range (%d-%d).",
+ hint, DM_THIN_MIN_DATA_BLOCK_SIZE, DM_THIN_MAX_DATA_BLOCK_SIZE);
+ } else
+ chunk_size = hint >= default_chunk_size ? hint : default_chunk_size;
+out:
+ first_seg(pool_lv)->chunk_size = chunk_size;
+ return 1;
+}
+
/* Thin notes:
* If lp->thin OR lp->activate is AY*, activate the pool if not already active.
* If lp->thin, create thin LV within the pool - as a snapshot if lp->snapshot.
return_NULL;
if (seg_is_thin_pool(lp)) {
+ if (!_recalculate_thin_pool_chunk_size_with_dev_hints(lp, lv))
+ return_NULL;
first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0;
- first_seg(lv)->chunk_size = lp->chunk_size;
first_seg(lv)->discards = lp->discards;
/* FIXME: use lowwatermark via lvm.conf global for all thinpools ? */
first_seg(lv)->low_water_mark = 0;