From: Joe Thornber <[email-masked]>

dm thin metadata: add a mode param to dm_pool_metadata_open

This allows the caller to permit a combination of 'open' or 'format'.

Signed-off-by: Joe Thornber <[email-masked]>
Signed-off-by: Mike Snitzer <[email-masked]>
---
 drivers/md/dm-thin-metadata.c |   17 ++++++++++-------
 drivers/md/dm-thin-metadata.h |    8 +++++++-
 drivers/md/dm-thin.c          |    2 +-
 3 files changed, 18 insertions(+), 9 deletions(-)

Index: linux/drivers/md/dm-thin-metadata.c
===================================================================
--- linux.orig/drivers/md/dm-thin-metadata.c
+++ linux/drivers/md/dm-thin-metadata.c
@@ -625,7 +625,8 @@ out_unlock_sblock:
 	return r;
 }
 
-static int __open_or_format_metadata(struct dm_pool_metadata *pmd)
+static int __open_or_format_metadata(struct dm_pool_metadata *pmd,
+				     enum dm_thin_metadata_mode mode)
 {
 	int r, unformatted;
 
@@ -634,12 +635,13 @@ static int __open_or_format_metadata(str
 		return r;
 
 	if (unformatted)
-		return __format_metadata(pmd);
+		return (mode & DM_THIN_FORMAT) ? __format_metadata(pmd) : -EPERM;
 	else
-		return __open_metadata(pmd);
+		return (mode & DM_THIN_OPEN) ? __open_metadata(pmd) : -EPERM;
 }
 
-static int __create_persistent_data_objects(struct dm_pool_metadata *pmd)
+static int __create_persistent_data_objects(struct dm_pool_metadata *pmd,
+					    enum dm_thin_metadata_mode mode)
 {
 	int r;
 
@@ -651,7 +653,7 @@ static int __create_persistent_data_obje
 		return PTR_ERR(pmd->bm);
 	}
 
-	r = __open_or_format_metadata(pmd);
+	r = __open_or_format_metadata(pmd, mode);
 	if (r)
 		dm_block_manager_destroy(pmd->bm);
 
@@ -793,7 +795,8 @@ out_locked:
 }
 
 struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
-					       sector_t data_block_size)
+					       sector_t data_block_size,
+					       enum dm_thin_metadata_mode mode)
 {
 	int r;
 	struct dm_pool_metadata *pmd;
@@ -810,7 +813,7 @@ struct dm_pool_metadata *dm_pool_metadat
 	pmd->bdev = bdev;
 	pmd->data_block_size = data_block_size;
 
-	r = __create_persistent_data_objects(pmd);
+	r = __create_persistent_data_objects(pmd, mode);
 	if (r) {
 		kfree(pmd);
 		return ERR_PTR(r);
Index: linux/drivers/md/dm-thin-metadata.h
===================================================================
--- linux.orig/drivers/md/dm-thin-metadata.h
+++ linux/drivers/md/dm-thin-metadata.h
@@ -37,8 +37,14 @@ typedef uint64_t dm_thin_id;
 /*
  * Reopens or creates a new, empty metadata volume.
  */
+enum dm_thin_metadata_mode {
+	DM_THIN_OPEN = 1,
+	DM_THIN_FORMAT = 2
+};
+
 struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
-					       sector_t data_block_size);
+					       sector_t data_block_size,
+					       enum dm_thin_metadata_mode mode);
 
 int dm_pool_metadata_close(struct dm_pool_metadata *pmd);
 
Index: linux/drivers/md/dm-thin.c
===================================================================
--- linux.orig/drivers/md/dm-thin.c
+++ linux/drivers/md/dm-thin.c
@@ -1712,7 +1712,7 @@ static struct pool *pool_create(struct m
 	struct pool *pool;
 	struct dm_pool_metadata *pmd;
 
-	pmd = dm_pool_metadata_open(metadata_dev, block_size);
+	pmd = dm_pool_metadata_open(metadata_dev, block_size, DM_THIN_FORMAT | DM_THIN_OPEN);
 	if (IS_ERR(pmd)) {
 		*error = "Error creating metadata object";
 		return (struct pool *)pmd;