*/
unsigned delay_resume_if_new;
+ /*
+ * Preload tree normally only loads and not resume, but there is
+ * automatic resume when target is extended, as it's believed
+ * there can be no i/o flying to this 'new' extedend space
+ * from any device above. Reason is that preloaded target above
+ * may actually need to see its bigger subdevice before it
+ * gets suspended. As long as devices are simple linears
+ * there is no problem to resume bigger device in preload (before commit).
+ * However complex targets like thin-pool (raid,cache...)
+ * they shall not be resumed before their commit.
+ */
+ unsigned delay_resume_if_extended;
+
/*
* Call node_send_messages(), set to 2 if there are messages
* When != 0, it validates matching transaction id, thus thin-pools
PRIu64 " for %s.%s", existing_table_size,
seg_start, _node_name(dnode),
dnode->props.size_changed ? "" : " (Ignoring.)");
+
+ /*
+ * FIXME: code here has known design problem.
+ * LVM2 does NOT resize thin-pool on top of other LV in 2 steps -
+ * where raid would be resized with 1st. transaction
+ * followed by 2nd. thin-pool resize - RHBZ #1285063
+ */
+ if (existing_table_size && dnode->props.delay_resume_if_extended) {
+ log_debug_activation("Resume of table of extended device %s delayed.",
+ _node_name(dnode));
+ dnode->props.size_changed = 0;
+ }
}
}
struct dm_tree_node *child;
struct dm_info newinfo;
int update_devs_flag = 0;
- struct load_segment *seg;
/* Preload children first */
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (!child->info.exists && !(node_created = _create_node(child)))
return_0;
+ /* Propagate delayed resume from exteded child node */
+ if (child->props.delay_resume_if_extended)
+ dnode->props.delay_resume_if_extended = 1;
+
if (!child->info.inactive_table &&
child->props.segment_count &&
!_load_node(child)) {
return_0;
}
- /* Propagate device size change change */
- if (child->props.size_changed > 0 && !dnode->props.size_changed)
- dnode->props.size_changed = 1;
- else if (child->props.size_changed < 0)
- dnode->props.size_changed = -1;
-
/* No resume for a device without parents or with unchanged or smaller size */
if (!dm_tree_node_num_children(child, 1) || (child->props.size_changed <= 0))
continue;
- if (!node_created && (dm_list_size(&child->props.segs) == 1)) {
- /* If thin-pool child nodes were preloaded WITH changed size
- * skip device resume, as this is likely resize of data or
- * metadata device and so thin pool needs suspend before
- * resume operation.
- * Note: child->props.segment_count is already 0 here
- */
- seg = dm_list_item(dm_list_last(&child->props.segs),
- struct load_segment);
- if (seg->type == SEG_THIN_POOL) {
- log_debug_activation("Skipping resume of thin-pool %s.",
- child->name);
- continue;
- }
- }
-
if (!child->info.inactive_table && !child->info.suspended)
continue;
seg->metadata->props.delay_resume_if_new = 0;
seg->pool->props.delay_resume_if_new = 0;
+ /* Preload must not resume extended running thin-pool before it's committed */
+ node->props.delay_resume_if_extended = 1;
+
/* Validate only transaction_id > 0 when activating thin-pool */
node->props.send_messages = transaction_id ? 1 : 0;
seg->transaction_id = transaction_id;