Let's find out if this makes things better or worse overall...
Version 2.02.86 -
=================================
+ When suspending, automatically preload newly-visible existing LVs.
Report internal error when parameters are missing on table load.
Teardown any stray devices with $COMMON_PREFIX during test runs.
Reinstate correct permissions when creating mirrors. [2.02.85]
#endif
}
+struct detached_lv_data {
+ struct logical_volume *lv_pre;
+ struct lv_activate_opts *laopts;
+ int *flush_required;
+};
+
+static int _preload_detached_lv(struct cmd_context *cmd, struct logical_volume *lv, void *data)
+{
+ struct detached_lv_data *detached = data;
+ struct lv_list *lvl_pre;
+
+ if ((lvl_pre = find_lv_in_vg(detached->lv_pre->vg, lv->name))) {
+ if (lv_is_visible(lvl_pre->lv) && lv_is_active(lv) &&
+ !_lv_preload(lvl_pre->lv, detached->laopts, detached->flush_required))
+ return_0;
+ }
+
+ return 1;
+}
+
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
struct lv_activate_opts *laopts, int error_if_not_suspended)
{
struct seg_list *sl;
struct lvinfo info;
int r = 0, lockfs = 0, flush_required = 0;
+ struct detached_lv_data detached;
if (!activation())
return 1;
}
if (!_lv_preload(lvl_pre->lv, laopts, &flush_required))
goto_out;
- } else if (!_lv_preload(lv_pre, laopts, &flush_required))
- /* FIXME Revert preloading */
- goto_out;
+ } else {
+ if (!_lv_preload(lv_pre, laopts, &flush_required))
+ /* FIXME Revert preloading */
+ goto_out;
+
+ /*
+ * Search for existing LVs that have become detached and preload them.
+ */
+ detached.lv_pre = lv_pre;
+ detached.laopts = laopts;
+ detached.flush_required = &flush_required;
+
+ if (!for_each_sub_lv(cmd, lv, &_preload_detached_lv, &detached))
+ goto_out;
+ }
}
if (!monitor_dev_for_events(cmd, lv, laopts, 0))
return NULL;
}
- if (!_add_lv_to_dtree(dm, dtree, lv, origin_only))
+ if (!_add_lv_to_dtree(dm, dtree, lv, lv_is_origin(lv) ? origin_only : 0))
goto_bad;
/* Add any snapshots of this LV */
- if (!origin_only)
+ if (!origin_only && lv_is_origin(lv))
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, 0))
goto_bad;
/* Restore fs cookie */
dm_tree_set_cookie(root, fs_get_cookie());
- if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, laopts->origin_only ? "real" : NULL)))
+ if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, (lv_is_origin(lv) && laopts->origin_only) ? "real" : NULL)))
goto_out;
/* Only process nodes with uuid of "LVM-" plus VG id. */
case PRELOAD:
case ACTIVATE:
/* Add all required new devices to tree */
- if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, laopts->origin_only ? "real" : NULL))
+ if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, (lv_is_origin(lv) && laopts->origin_only) ? "real" : NULL))
goto_out;
/* Preload any devices required before any suspensions */
return _rename_single_lv(lv, new_name);
}
-/* Callback for _for_each_sub_lv */
+/* Callback for for_each_sub_lv */
static int _rename_cb(struct cmd_context *cmd, struct logical_volume *lv,
void *data)
{
}
/*
- * Loop down sub LVs and call "func" for each.
- * "func" is responsible to log necessary information on failure.
+ * Loop down sub LVs and call fn for each.
+ * fn is responsible to log necessary information on failure.
*/
-static int _for_each_sub_lv(struct cmd_context *cmd, struct logical_volume *lv,
- int (*func)(struct cmd_context *cmd,
- struct logical_volume *lv,
- void *data),
- void *data)
+int for_each_sub_lv(struct cmd_context *cmd, struct logical_volume *lv,
+ int (*fn)(struct cmd_context *cmd,
+ struct logical_volume *lv, void *data),
+ void *data)
{
struct logical_volume *org;
struct lv_segment *seg;
uint32_t s;
if (lv_is_cow(lv) && lv_is_virtual_origin(org = origin_from_cow(lv)))
- if (!func(cmd, org, data))
+ if (!fn(cmd, org, data))
return_0;
dm_list_iterate_items(seg, &lv->segments) {
- if (seg->log_lv && !func(cmd, seg->log_lv, data))
+ if (seg->log_lv && !fn(cmd, seg->log_lv, data))
return_0;
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) != AREA_LV)
continue;
- if (!func(cmd, seg_lv(seg, s), data))
+ if (!fn(cmd, seg_lv(seg, s), data))
return_0;
- if (!_for_each_sub_lv(cmd, seg_lv(seg, s), func, data))
+ if (!for_each_sub_lv(cmd, seg_lv(seg, s), fn, data))
return_0;
}
}
/* rename sub LVs */
lv_names.old = lv->name;
lv_names.new = new_name;
- if (!_for_each_sub_lv(cmd, lv, _rename_cb, (void *) &lv_names))
+ if (!for_each_sub_lv(cmd, lv, _rename_cb, (void *) &lv_names))
return 0;
/* rename main LV */
int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv);
+int for_each_sub_lv(struct cmd_context *cmd, struct logical_volume *lv,
+ int (*fn)(struct cmd_context *cmd,
+ struct logical_volume *lv, void *data),
+ void *data);
+
/*
* Calculate readahead from underlying PV devices
*/