[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] pvmove hangs while operating with heavy I/O stress



Hi all,
  When there're several LVs on $PV1, and there is heavy I/O on several LVs,
"pvmove $PV1 $PV2" may hang forever in suspend_lv.
  This is because suspend_lvs iterates the list of LVs, and suspends them all.
While suspend_lv has already suspend the underlying mirror table, following
suspend_lv may sleep forever, waiting for IO flushing.

  The attached patch is a direct attack the problem. But it may be better to
fix suspend_lvs directly.

  Any comments ?

  Thanks.
diff --git a/lib/locking/locking.c b/lib/locking/locking.c
index 98f17a7..2f8916d 100644
--- a/lib/locking/locking.c
+++ b/lib/locking/locking.c
@@ -489,6 +489,27 @@ int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs)
 	return r;
 }
 
+/* Lock a list of LVs, but always resume the exception */
+int suspend_lvs_exp(struct cmd_context *cmd, struct dm_list *lvs, struct logical_volume *exp)
+{
+	struct dm_list *lvh;
+	struct lv_list *lvl;
+
+	dm_list_iterate_items(lvl, lvs) {
+		if (!suspend_lv(cmd, lvl->lv)) {
+			log_error("Failed to suspend %s", lvl->lv->name);
+			dm_list_uniterate(lvh, lvs, &lvl->list) {
+				lvl = dm_list_item(lvh, struct lv_list);
+				if (!resume_lv(cmd, lvl->lv))
+					stack;
+			}
+
+			return 0;
+		}
+		resume_lv(cmd, exp);
+	}
+	return 1;
+}
 /* Lock a list of LVs */
 int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs)
 {
diff --git a/lib/locking/locking.h b/lib/locking/locking.h
index 5b13791..245a837 100644
--- a/lib/locking/locking.h
+++ b/lib/locking/locking.h
@@ -185,6 +185,7 @@ int sync_local_dev_names(struct cmd_context* cmd);
 int sync_dev_names(struct cmd_context* cmd);
 
 /* Process list of LVs */
+int suspend_lvs_exp(struct cmd_context *cmd, struct dm_list *lvs, struct logical_volume *exp);
 int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs);
 int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs);
 int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive);
diff --git a/tools/pvmove.c b/tools/pvmove.c
index 51f442f..47a00ef 100644
--- a/tools/pvmove.c
+++ b/tools/pvmove.c
@@ -320,9 +320,16 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
 	}
 
 	/* Suspend lvs_changed */
-	if (!suspend_lvs(cmd, lvs_changed)) {
-		vg_revert(vg);
-		goto_out;
+	if (first_time) {
+		if (!suspend_lvs(cmd, lvs_changed)) {
+			vg_revert(vg);
+			goto_out;
+		}
+	} else {
+		if (!suspend_lvs(cmd, lvs_change, lv_mirr)) {
+			vg_revert(vg);
+			goto_out;
+		}
 	}
 
 	/* Suspend mirrors on subsequent calls */
@@ -534,7 +541,7 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
 	}
 
 	/* Suspend LVs changed */
-	if (!suspend_lvs(cmd, lvs_changed)) {
+	if (!suspend_lvs_exp(cmd, lvs_changed, lv_mirror)) {
 		log_error("Locking LVs to remove temporary mirror failed");
 		r = 0;
 	}

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]