From: Mike Snitzer <[email-masked]>

Factor out __check_incompat_features and only call it once when we open
the metadata device rather than at the beginning of every transaction.

Signed-off-by: Mike Snitzer <[email-masked]>
Signed-off-by: Joe Thornber <[email-masked]>
Signed-off-by: Alasdair G Kergon <[email-masked]>
---
 drivers/md/dm-thin-metadata.c |   62 ++++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 26 deletions(-)

Index: linux/drivers/md/dm-thin-metadata.c
===================================================================
--- linux.orig/drivers/md/dm-thin-metadata.c
+++ linux/drivers/md/dm-thin-metadata.c
@@ -537,6 +537,34 @@ bad:
 	return r;
 }
 
+static int __check_incompat_features(struct thin_disk_superblock *disk_super,
+				     struct dm_pool_metadata *pmd)
+{
+	uint32_t features;
+
+	features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP;
+	if (features) {
+		DMERR("could not access metadata due to unsupported optional features (%lx).",
+		      (unsigned long)features);
+		return -EINVAL;
+	}
+
+	/*
+	 * Check for read-only metadata to skip the following RDWR checks.
+	 */
+	if (get_disk_ro(pmd->bdev->bd_disk))
+		return 0;
+
+	features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP;
+	if (features) {
+		DMERR("could not access metadata RDWR due to unsupported optional features (%lx).",
+		      (unsigned long)features);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int __open_metadata(struct dm_pool_metadata *pmd)
 {
 	int r;
@@ -551,6 +579,13 @@ static int __open_metadata(struct dm_poo
 	}
 
 	disk_super = dm_block_data(sblock);
+
+	r = __check_incompat_features(disk_super, pmd);
+	if (r < 0) {
+		dm_bm_unlock(sblock);
+		return r;
+	}
+
 	r = dm_tm_open_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION,
 			       disk_super->metadata_space_map_root,
 			       sizeof(disk_super->metadata_space_map_root),
@@ -635,7 +670,6 @@ static void __destroy_persistent_data_ob
 static int __begin_transaction(struct dm_pool_metadata *pmd)
 {
 	int r;
-	u32 features;
 	struct thin_disk_superblock *disk_super;
 	struct dm_block *sblock;
 
@@ -656,32 +690,8 @@ static int __begin_transaction(struct dm
 	pmd->flags = le32_to_cpu(disk_super->flags);
 	pmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
 
-	features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP;
-	if (features) {
-		DMERR("could not access metadata due to "
-		      "unsupported optional features (%lx).",
-		      (unsigned long)features);
-		r = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Check for read-only metadata to skip the following RDWR checks.
-	 */
-	if (get_disk_ro(pmd->bdev->bd_disk))
-		goto out;
-
-	features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP;
-	if (features) {
-		DMERR("could not access metadata RDWR due to "
-		      "unsupported optional features (%lx).",
-		      (unsigned long)features);
-		r = -EINVAL;
-	}
-
-out:
 	dm_bm_unlock(sblock);
-	return r;
+	return 0;
 }
 
 static int __write_changed_details(struct dm_pool_metadata *pmd)