]> sourceware.org Git - lvm2.git/commitdiff
activate: Improve snapshot merge initiation
authorAlasdair G Kergon <agk@redhat.com>
Fri, 15 Apr 2016 01:21:27 +0000 (02:21 +0100)
committerAlasdair G Kergon <agk@redhat.com>
Fri, 15 Apr 2016 01:33:38 +0000 (02:33 +0100)
A snapshot merge into its origin cannot be initiated while the devices
are in use.  If there is outside interference (such as from udev),
the suspend (preload) and resume stages can reach conflicting decisions
about whether or not to proceed.

Try to make the logic more robust by checking the inactive or live
table during resume.  (This is still not perfect.)

WHATS_NEW
lib/activate/activate.c
lib/activate/activate.h
lib/activate/dev_manager.c

index 8c58c8d9164a3213d5ced93981744639f8383148..123c3839086289df6ea1f36e1274ec61e741d981 100644 (file)
--- 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.
index 8e6ee33c9a95d25b5398faad9edf38d02dfdaed3..ac547ce5b9cbb2c416aa750f396b8c591d848593 100644 (file)
@@ -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;
index 64c026ee49bfdeace7aca3e785691fef608339aa..880689cee19e35f0c542918d38e63941451a2362 100644 (file)
@@ -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);
index d25c07ebd463fe1dc9f20061af1c79304bbae2da..92f2a05d7ea82f39bb178e184be4bc72fa62d10e 100644 (file)
@@ -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, &params);
-               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;
                }
        }
 
This page took 0.06523 seconds and 5 git commands to generate.