Blame SOURCES/0019-thin_check-Allow-using-clear-needs-check-and-skip-ma.patch

8f6cbb
From 6ce838b83c28d9b64f34cf0c68cfebaf9affac11 Mon Sep 17 00:00:00 2001
8f6cbb
From: Ming-Hung Tsai <mtsai@redhat.com>
8f6cbb
Date: Fri, 21 Aug 2020 18:26:48 +0800
8f6cbb
Subject: [PATCH] [thin_check] Allow using --clear-needs-check and
8f6cbb
 --skip-mappings together
8f6cbb
8f6cbb
Although it is not recommended to clear the flag without a full
8f6cbb
examination, however, the usage has been documented as an approach
8f6cbb
to reduce lvchange run time [1]. For the purpose of backward
8f6cbb
compatibility and avoiding boot failure after upgrading thin_check [2],
8f6cbb
the limitation is now removed.
8f6cbb
8f6cbb
[1] https://wiki.archlinux.org/index.php/LVM#Thinly-provisioned_root_volume_device_times_out
8f6cbb
[2] Community feedback on previous commit:
8f6cbb
    https://github.com/jthornber/thin-provisioning-tools/commit/b278f4f
8f6cbb
8f6cbb
(cherry picked from commit f4675e3f32aad3d1518869e4f3824e05230c6a5d)
8f6cbb
---
8f6cbb
 functional-tests/thin-functional-tests.scm | 65 +++++++++++++---
8f6cbb
 thin-provisioning/metadata_checker.cc      | 88 +++++++++++-----------
8f6cbb
 thin-provisioning/metadata_checker.h       |  5 +-
8f6cbb
 thin-provisioning/thin_check.cc            |  2 +-
8f6cbb
 4 files changed, 106 insertions(+), 54 deletions(-)
8f6cbb
8f6cbb
diff --git a/functional-tests/thin-functional-tests.scm b/functional-tests/thin-functional-tests.scm
8f6cbb
index 37d3df9..5b1423c 100644
8f6cbb
--- a/functional-tests/thin-functional-tests.scm
8f6cbb
+++ b/functional-tests/thin-functional-tests.scm
8f6cbb
@@ -189,15 +189,6 @@
8f6cbb
       (run-fail (thin-check "--auto-repair" "--skip-mappings" md))
8f6cbb
       (run-fail (thin-check "--auto-repair" "--ignore-non-fatal-errors" md))))
8f6cbb
 
8f6cbb
-  (define-scenario (thin-check incompatible-options clear-needs-check-flag)
8f6cbb
-    "Incompatible options should cause failure"
8f6cbb
-    (with-valid-metadata (md)
8f6cbb
-      (run-fail (thin-check "--clear-needs-check-flag" "-m" md))
8f6cbb
-      (run-fail (thin-check "--clear-needs-check-flag" "--override-mapping-root 123" md))
8f6cbb
-      (run-fail (thin-check "--clear-needs-check-flag" "--super-block-only" md))
8f6cbb
-      (run-fail (thin-check "--clear-needs-check-flag" "--skip-mappings" md))
8f6cbb
-      (run-fail (thin-check "--clear-needs-check-flag" "--ignore-non-fatal-errors" md))))
8f6cbb
-
8f6cbb
   (define-scenario (thin-check superblock-only-valid)
8f6cbb
     "--super-block-only check passes on valid metadata"
8f6cbb
     (with-valid-metadata (md)
8f6cbb
@@ -230,6 +221,62 @@
8f6cbb
     (with-valid-metadata (md)
8f6cbb
       (run-ok (thin-check "--clear-needs-check-flag" md))))
8f6cbb
 
8f6cbb
+  (define-scenario (thin-check mixing-clear-needs-check-flag super-block-only-should-pass)
8f6cbb
+    "Accepts --clear-needs-check and --super-block-only"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" "--super-block-only" md))))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check mixing-clear-needs-check-flag skip-mappings-should-pass)
8f6cbb
+    "Accepts --clear-needs-check and --skip-mappings"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" "--skip-mappings" md))))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check mixing-clear-needs-check-flag ignore-non-fatal-errors-should-pass)
8f6cbb
+    "Accepts --clear-needs-check and --ignore-non-fatal-errors"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" "--ignore-non-fatal-errors" md))))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check try-clear-needs-check-flag super-block-only-should-clear)
8f6cbb
+    "--clear-needs-check is a noop while using --super-block-only"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (set-needs-check-flag md)
8f6cbb
+      (assert-metadata-needs-check md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" "--super-block-only" md))
8f6cbb
+      (assert-metadata-clean md)))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check try-clear-needs-check-flag skip-mappings-should-clear)
8f6cbb
+    "--clear-needs-check is a noop while using --skip-mappings"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (set-needs-check-flag md)
8f6cbb
+      (assert-metadata-needs-check md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" "--skip-mappings" md))
8f6cbb
+      (assert-metadata-clean md)))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check try-clear-needs-check-flag ignore-non-fatal-errors-should-clear)
8f6cbb
+    "--clear-needs-check works while using --ignore-non-fatal-errors"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (set-needs-check-flag md)
8f6cbb
+      (assert-metadata-needs-check md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" "--ignore-non-fatal-errors" md))
8f6cbb
+      (assert-metadata-clean md)))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check try-clear-needs-check-flag no-errors-should-clear)
8f6cbb
+    "--clear-needs-check works if there's no errors"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (set-needs-check-flag md)
8f6cbb
+      (assert-metadata-needs-check md)
8f6cbb
+      (run-ok (thin-check "--clear-needs-check-flag" md))
8f6cbb
+      (assert-metadata-clean md)))
8f6cbb
+
8f6cbb
+  (define-scenario (thin-check try-clear-needs-check-flag fatal-errors-should-keep)
8f6cbb
+    "--clear-needs-check is a noop if there's fatal errors"
8f6cbb
+    (with-valid-metadata (md)
8f6cbb
+      (set-needs-check-flag md)
8f6cbb
+      (tamper-mapping-root md 10)
8f6cbb
+      (assert-metadata-needs-check md)
8f6cbb
+      (run-fail (thin-check "--clear-needs-check-flag" md))
8f6cbb
+      (assert-metadata-needs-check md)))
8f6cbb
+
8f6cbb
   (define-scenario (thin-check auto-repair)
8f6cbb
     "Accepts --auto-repair"
8f6cbb
     (with-valid-metadata (md)
8f6cbb
diff --git a/thin-provisioning/metadata_checker.cc b/thin-provisioning/metadata_checker.cc
8f6cbb
index e81e22c..1c9734e 100644
8f6cbb
--- a/thin-provisioning/metadata_checker.cc
8f6cbb
+++ b/thin-provisioning/metadata_checker.cc
8f6cbb
@@ -371,7 +371,8 @@ namespace {
8f6cbb
 			  out_(cerr, 2),
8f6cbb
 			  info_out_(cout, 0),
8f6cbb
 			  expected_rc_(true), // set stop on the first error
8f6cbb
-			  err_(NO_ERROR) {
8f6cbb
+			  err_(NO_ERROR),
8f6cbb
+			  metadata_checked_(false) {
8f6cbb
 
8f6cbb
 			if (output_opts == OUTPUT_QUIET) {
8f6cbb
 				out_.disable();
8f6cbb
@@ -381,7 +382,29 @@ namespace {
8f6cbb
 			sb_location_ = get_superblock_location();
8f6cbb
 		}
8f6cbb
 
8f6cbb
-		void check() {
8f6cbb
+		void check_and_repair() {
8f6cbb
+			if (!check())
8f6cbb
+				return;
8f6cbb
+
8f6cbb
+			if (!options_.use_metadata_snap_ &&
8f6cbb
+			    !options_.override_mapping_root_) {
8f6cbb
+				if (options_.sm_opts_ == check_options::SPACE_MAP_FULL &&
8f6cbb
+				    options_.fix_metadata_leaks_)
8f6cbb
+					fix_metadata_leaks(options_.open_transaction_);
8f6cbb
+				if (options_.clear_needs_check_)
8f6cbb
+					clear_needs_check_flag();
8f6cbb
+			}
8f6cbb
+		}
8f6cbb
+
8f6cbb
+		bool get_status() const {
8f6cbb
+			if (options_.ignore_non_fatal_)
8f6cbb
+				return (err_ == FATAL) ? false : true;
8f6cbb
+
8f6cbb
+			return (err_ == NO_ERROR) ? true : false;
8f6cbb
+		}
8f6cbb
+
8f6cbb
+	private:
8f6cbb
+		bool check() {
8f6cbb
 			block_manager::ptr bm = open_bm(path_, block_manager::READ_ONLY,
8f6cbb
 							!options_.use_metadata_snap_);
8f6cbb
 
8f6cbb
@@ -389,7 +412,7 @@ namespace {
8f6cbb
 			if (err_ == FATAL) {
8f6cbb
 				if (check_for_xml(bm))
8f6cbb
 					out_ << "This looks like XML.  thin_check only checks the binary metadata format." << end_message();
8f6cbb
-				return;
8f6cbb
+				return false;
8f6cbb
 			}
8f6cbb
 
8f6cbb
 			transaction_manager::ptr tm = open_tm(bm, sb_location_);
8f6cbb
@@ -407,7 +430,7 @@ namespace {
8f6cbb
 				err_ << examine_data_mappings(tm, sb, options_.data_mapping_opts_, out_, core_sm);
8f6cbb
 
8f6cbb
 				if (err_ == FATAL)
8f6cbb
-					return;
8f6cbb
+					return false;
8f6cbb
 
8f6cbb
 				// if we're checking everything, and there were no errors,
8f6cbb
 				// then we should check the space maps too.
8f6cbb
@@ -419,10 +442,14 @@ namespace {
8f6cbb
 			} else
8f6cbb
 				err_ << examine_data_mappings(tm, sb, options_.data_mapping_opts_, out_,
8f6cbb
 							      optional<space_map::ptr>());
8f6cbb
+
8f6cbb
+			metadata_checked_ = true;
8f6cbb
+
8f6cbb
+			return true;
8f6cbb
 		}
8f6cbb
 
8f6cbb
 		bool fix_metadata_leaks(bool open_transaction) {
8f6cbb
-			if (!verify_preconditions_before_fixing()) {
8f6cbb
+			if (!metadata_checked_) {
8f6cbb
 				out_ << "metadata has not been fully examined" << end_message();
8f6cbb
 				return false;
8f6cbb
 			}
8f6cbb
@@ -458,12 +485,13 @@ namespace {
8f6cbb
 		}
8f6cbb
 
8f6cbb
 		bool clear_needs_check_flag() {
8f6cbb
-			if (!verify_preconditions_before_fixing()) {
8f6cbb
+			if (!metadata_checked_) {
8f6cbb
 				out_ << "metadata has not been fully examined" << end_message();
8f6cbb
 				return false;
8f6cbb
 			}
8f6cbb
 
8f6cbb
-			if (err_ != NO_ERROR)
8f6cbb
+			if (err_ == FATAL ||
8f6cbb
+			    (err_ == NON_FATAL && !options_.ignore_non_fatal_))
8f6cbb
 				return false;
8f6cbb
 
8f6cbb
 			block_manager::ptr bm = open_bm(path_, block_manager::READ_WRITE);
8f6cbb
@@ -480,14 +508,6 @@ namespace {
8f6cbb
 			return true;
8f6cbb
 		}
8f6cbb
 
8f6cbb
-		bool get_status() const {
8f6cbb
-			if (options_.ignore_non_fatal_)
8f6cbb
-				return (err_ == FATAL) ? false : true;
8f6cbb
-
8f6cbb
-			return (err_ == NO_ERROR) ? true : false;
8f6cbb
-		}
8f6cbb
-
8f6cbb
-	private:
8f6cbb
 		block_address
8f6cbb
 		get_superblock_location() {
8f6cbb
 			block_address sb_location = superblock_detail::SUPERBLOCK_LOCATION;
8f6cbb
@@ -545,19 +565,6 @@ namespace {
8f6cbb
 			return err;
8f6cbb
 		}
8f6cbb
 
8f6cbb
-		bool verify_preconditions_before_fixing() const {
8f6cbb
-			if (options_.use_metadata_snap_ ||
8f6cbb
-			    !!options_.override_mapping_root_ ||
8f6cbb
-			    options_.sm_opts_ != check_options::SPACE_MAP_FULL ||
8f6cbb
-			    options_.data_mapping_opts_ != check_options::DATA_MAPPING_LEVEL2)
8f6cbb
-				return false;
8f6cbb
-
8f6cbb
-			if (!expected_rc_.get_counts().size())
8f6cbb
-				return false;
8f6cbb
-
8f6cbb
-			return true;
8f6cbb
-		}
8f6cbb
-
8f6cbb
 		std::string const &path_;
8f6cbb
 		check_options options_;
8f6cbb
 		nested_output out_;
8f6cbb
@@ -565,6 +572,7 @@ namespace {
8f6cbb
 		block_address sb_location_;
8f6cbb
 		block_counter expected_rc_;
8f6cbb
 		base::error_state err_; // metadata state
8f6cbb
+		bool metadata_checked_;
8f6cbb
 	};
8f6cbb
 }
8f6cbb
 
8f6cbb
@@ -603,8 +611,9 @@ void check_options::set_ignore_non_fatal() {
8f6cbb
 	ignore_non_fatal_ = true;
8f6cbb
 }
8f6cbb
 
8f6cbb
-void check_options::set_fix_metadata_leaks() {
8f6cbb
+void check_options::set_auto_repair() {
8f6cbb
 	fix_metadata_leaks_ = true;
8f6cbb
+	clear_needs_check_ = true;
8f6cbb
 }
8f6cbb
 
8f6cbb
 void check_options::set_clear_needs_check() {
8f6cbb
@@ -612,7 +621,7 @@ void check_options::set_clear_needs_check() {
8f6cbb
 }
8f6cbb
 
8f6cbb
 bool check_options::check_conformance() {
8f6cbb
-	if (fix_metadata_leaks_ || clear_needs_check_) {
8f6cbb
+	if (fix_metadata_leaks_) {
8f6cbb
 		if (ignore_non_fatal_) {
8f6cbb
 			cerr << "cannot perform fix by ignoring non-fatal errors" << endl;
8f6cbb
 			return false;
8f6cbb
@@ -627,12 +636,12 @@ bool check_options::check_conformance() {
8f6cbb
 			cerr << "cannot perform fix with an overridden mapping root" << endl;
8f6cbb
 			return false;
8f6cbb
 		}
8f6cbb
+	}
8f6cbb
 
8f6cbb
-		if (data_mapping_opts_ != DATA_MAPPING_LEVEL2 ||
8f6cbb
-		    sm_opts_ != SPACE_MAP_FULL) {
8f6cbb
-			cerr << "cannot perform fix without a full examination" << endl;
8f6cbb
-			return false;
8f6cbb
-		}
8f6cbb
+	if (fix_metadata_leaks_ &&
8f6cbb
+	    (data_mapping_opts_ != DATA_MAPPING_LEVEL2 || sm_opts_ != SPACE_MAP_FULL)) {
8f6cbb
+		cerr << "cannot perform fix without a full examination" << endl;
8f6cbb
+		return false;
8f6cbb
 	}
8f6cbb
 
8f6cbb
 	return true;
8f6cbb
@@ -646,14 +655,7 @@ thin_provisioning::check_metadata(std::string const &path,
8f6cbb
 				  output_options output_opts)
8f6cbb
 {
8f6cbb
 	metadata_checker checker(path, check_opts, output_opts);
8f6cbb
-
8f6cbb
-	checker.check();
8f6cbb
-	if (check_opts.fix_metadata_leaks_)
8f6cbb
-		checker.fix_metadata_leaks(check_opts.open_transaction_);
8f6cbb
-	if (check_opts.fix_metadata_leaks_ ||
8f6cbb
-	    check_opts.clear_needs_check_)
8f6cbb
-		checker.clear_needs_check_flag();
8f6cbb
-
8f6cbb
+	checker.check_and_repair();
8f6cbb
 	return checker.get_status();
8f6cbb
 }
8f6cbb
 
8f6cbb
diff --git a/thin-provisioning/metadata_checker.h b/thin-provisioning/metadata_checker.h
8f6cbb
index 5569d27..ea66dc3 100644
8f6cbb
--- a/thin-provisioning/metadata_checker.h
8f6cbb
+++ b/thin-provisioning/metadata_checker.h
8f6cbb
@@ -45,14 +45,17 @@ namespace thin_provisioning {
8f6cbb
 		void set_override_mapping_root(bcache::block_address b);
8f6cbb
 		void set_metadata_snap();
8f6cbb
 		void set_ignore_non_fatal();
8f6cbb
-		void set_fix_metadata_leaks();
8f6cbb
+		void set_auto_repair();
8f6cbb
 		void set_clear_needs_check();
8f6cbb
 
8f6cbb
+		// flags for checking
8f6cbb
 		bool use_metadata_snap_;
8f6cbb
 		data_mapping_options data_mapping_opts_;
8f6cbb
 		space_map_options sm_opts_;
8f6cbb
 		boost::optional<bcache::block_address> override_mapping_root_;
8f6cbb
 		bool ignore_non_fatal_;
8f6cbb
+
8f6cbb
+		// flags for repairing
8f6cbb
 		bool fix_metadata_leaks_;
8f6cbb
 		bool clear_needs_check_;
8f6cbb
 		bool open_transaction_;
8f6cbb
diff --git a/thin-provisioning/thin_check.cc b/thin-provisioning/thin_check.cc
8f6cbb
index 60f7838..e3c9db3 100644
8f6cbb
--- a/thin-provisioning/thin_check.cc
8f6cbb
+++ b/thin-provisioning/thin_check.cc
8f6cbb
@@ -166,7 +166,7 @@ thin_check_cmd::run(int argc, char **argv)
8f6cbb
 
8f6cbb
 		case 6:
8f6cbb
 			// auto-repair
8f6cbb
-			fs.check_opts.set_fix_metadata_leaks();
8f6cbb
+			fs.check_opts.set_auto_repair();
8f6cbb
 			break;
8f6cbb
 
8f6cbb
 		default:
8f6cbb
-- 
8f6cbb
2.31.1
8f6cbb