diff --git a/WHATS_NEW b/WHATS_NEW index 8c58c8d91..123c38390 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.151 - ================================= + Avoid deciding to initiate a pending snapshot merge during resume. Improve retrying lvmetad requests while lvmetad is being updated. Read devices instead of using the lvmetad cache if rescan fails. Move lvmetad token/filter check and device rescan to the start of commands. diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 8e6ee33c9..ac547ce5b 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -2063,6 +2063,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s, } laopts->read_only = _passes_readonly_filter(cmd, lv); + laopts->resuming = 1; if (!_lv_activate_lv(lv, laopts)) goto_out; diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 64c026ee4..880689cee 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -81,6 +81,7 @@ struct lv_activate_opts { * set of flags to avoid any scanning in udev. These udev * flags are persistent in udev db for any spurious event * that follows. */ + unsigned resuming; /* Set when resuming after a suspend. */ }; void set_activation(int activation, int silent); diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index d25c07ebd..92f2a05d7 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -806,13 +806,28 @@ int lv_has_target_type(struct dm_pool *mem, const struct logical_volume *lv, if (!dm_task_get_info(dmt, &info) || !info.exists) goto_out; + /* If there is a preloaded table, use that in preference. */ + if (info.inactive_table) { + dm_task_destroy(dmt); + + if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0))) + goto_bad; + + if (!dm_task_query_inactive_table(dmt)) + goto_out; + + if (!dm_task_run(dmt)) + goto_out; + + if (!dm_task_get_info(dmt, &info) || !info.exists || !info.inactive_table) + goto_out; + } + do { next = dm_get_next_target(dmt, next, &start, &length, &type, ¶ms); - if (type && strncmp(type, target_type, - strlen(target_type)) == 0) { - if (info.live_table) - r = 1; + if (type && !strncmp(type, target_type, strlen(target_type))) { + r = 1; break; } } while (next); @@ -2665,6 +2680,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, uint32_t read_ahead = lv->read_ahead; uint32_t read_ahead_flags = UINT32_C(0); int save_pending_delete = dm->track_pending_delete; + int snap_dev_is_open = 0; /* LV with pending delete is never put new into a table */ if (lv_is_pending_delete(lv) && !_cached_dm_info(dm->mem, dtree, lv, NULL)) @@ -2697,13 +2713,15 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, ((dinfo = _cached_dm_info(dm->mem, dtree, seg_is_thin_volume(seg) ? seg->lv : seg->cow, NULL)) && - dinfo->open_count)) { - if (seg_is_thin_volume(seg) || - /* FIXME Is there anything simpler to check for instead? */ - !lv_has_target_type(dm->mem, lv, NULL, TARGET_NAME_SNAPSHOT_MERGE)) { - log_debug_activation("Postponing pending snapshot merge for origin LV %s.", display_lvname(lv)); - laopts->no_merging = 1; - } + dinfo->open_count)) + snap_dev_is_open = 1; + + /* Preload considers open devices. */ + /* Resume looks at the table that will be the live one after the operation. */ + if ((!laopts->resuming && snap_dev_is_open && (seg_is_thin_volume(seg) || !lv_has_target_type(dm->mem, lv, NULL, TARGET_NAME_SNAPSHOT_MERGE))) || + (laopts->resuming && !seg_is_thin_volume(seg) && !lv_has_target_type(dm->mem, lv, NULL, TARGET_NAME_SNAPSHOT_MERGE))) { + log_debug_activation("Postponing pending snapshot merge for origin LV %s.", display_lvname(lv)); + laopts->no_merging = 1; } }