All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] dm thin metadata: handful of improvements
@ 2019-04-15 21:17 Mike Snitzer
  2019-04-15 21:17 ` [PATCH 1/3] dm space map common: zero entire ll_disk Mike Snitzer
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Mike Snitzer @ 2019-04-15 21:17 UTC (permalink / raw)
  To: dm-devel; +Cc: ejt

All are working well in my testing but I'd appreciate further review
from others.

Thanks,
Mike

Mike Snitzer (3):
  dm space map common: zero entire ll_disk
  dm thin metadata: do not write metadata if no changes occurred
  dm thin metadata: check __commit_transaction()'s return

 drivers/md/dm-thin-metadata.c                 | 63 +++++++++++++------
 .../md/persistent-data/dm-space-map-common.c  |  2 +
 2 files changed, 47 insertions(+), 18 deletions(-)

-- 
2.18.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] dm space map common: zero entire ll_disk
  2019-04-15 21:17 [PATCH 0/3] dm thin metadata: handful of improvements Mike Snitzer
@ 2019-04-15 21:17 ` Mike Snitzer
  2019-04-15 21:17 ` [PATCH 2/3] dm thin metadata: do not write metadata if no changes occurred Mike Snitzer
  2019-04-15 21:17 ` [PATCH 3/3] dm thin metadata: check __commit_transaction()'s return Mike Snitzer
  2 siblings, 0 replies; 6+ messages in thread
From: Mike Snitzer @ 2019-04-15 21:17 UTC (permalink / raw)
  To: dm-devel; +Cc: ejt

Otherwise, memory that is allocated (and potentially not previously
zeroed) will get written to disk as part of the space maps.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/persistent-data/dm-space-map-common.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index 0a3b8ae4a29c..b8a62188f6be 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -190,6 +190,8 @@ static int sm_find_free(void *addr, unsigned begin, unsigned end,
 
 static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
 {
+	memset(ll, 0, sizeof(struct ll_disk));
+
 	ll->tm = tm;
 
 	ll->bitmap_info.tm = tm;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] dm thin metadata: do not write metadata if no changes occurred
  2019-04-15 21:17 [PATCH 0/3] dm thin metadata: handful of improvements Mike Snitzer
  2019-04-15 21:17 ` [PATCH 1/3] dm space map common: zero entire ll_disk Mike Snitzer
@ 2019-04-15 21:17 ` Mike Snitzer
  2019-04-16  2:39   ` Mike Snitzer
  2019-04-15 21:17 ` [PATCH 3/3] dm thin metadata: check __commit_transaction()'s return Mike Snitzer
  2 siblings, 1 reply; 6+ messages in thread
From: Mike Snitzer @ 2019-04-15 21:17 UTC (permalink / raw)
  To: dm-devel; +Cc: ejt

Otherwise, just loading a thin-pool and then removing it will cause its
metadata to be changed (e.g. superblock written) -- even without any
thin devices being made active or metadata snapshot being manipulated.

Add 'changed' flag to struct dm_pool_metadata.  Set both td->changed and
pmd->changed using __set_thin_changed() -- this assures pmd->changed is
always set when td->changed is.  For methods that don't involve changing
a td, set pmd->changed directly.

Rename __delete_device() to __delete_thin() -- improves symmetry with
__create_thin().

Update dm_pool_changed_this_transaction() to simply return pmd->changed.

Fix dm_pool_commit_metadata() to open the next transaction if the return
from __commit_transaction() is 0.  Not seeing why the early return ever
made since for a return of 0 given that dm-io's async_io(), as used by
bufio, always returns 0.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/dm-thin-metadata.c | 56 ++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index ed3caceaed07..f4e8327abc75 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -201,6 +201,12 @@ struct dm_pool_metadata {
 	 */
 	bool fail_io:1;
 
+	/*
+	 * Set if metadata has changed, particularly important for methods that
+	 * alter metadata without the ability to reflect the change in td->changed.
+	 */
+	bool changed:1;
+
 	/*
 	 * Reading the space map roots can fail, so we read it into these
 	 * buffers before the superblock is locked and updated.
@@ -769,7 +775,7 @@ static int __write_changed_details(struct dm_pool_metadata *pmd)
 			return r;
 
 		if (td->open_count)
-			td->changed = 0;
+			td->changed = false;
 		else {
 			list_del(&td->list);
 			kfree(td);
@@ -779,6 +785,14 @@ static int __write_changed_details(struct dm_pool_metadata *pmd)
 	return 0;
 }
 
+static void __set_thin_changed(struct dm_thin_device *td)
+{
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	td->changed = true;
+	pmd->changed = true;
+}
+
 static int __commit_transaction(struct dm_pool_metadata *pmd)
 {
 	int r;
@@ -790,6 +804,9 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
 	 */
 	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
 
+	if (!pmd->changed)
+		return 0;
+
 	r = __write_changed_details(pmd);
 	if (r < 0)
 		return r;
@@ -819,6 +836,8 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
 
 	copy_sm_roots(pmd, disk_super);
 
+	pmd->changed = false;
+
 	return dm_tm_commit(pmd->tm, sblock);
 }
 
@@ -853,6 +872,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
 	pmd->time = 0;
 	INIT_LIST_HEAD(&pmd->thin_devices);
 	pmd->fail_io = false;
+	pmd->changed = false;
 	pmd->bdev = bdev;
 	pmd->data_block_size = data_block_size;
 
@@ -967,7 +987,8 @@ static int __open_device(struct dm_pool_metadata *pmd,
 	(*td)->pmd = pmd;
 	(*td)->id = dev;
 	(*td)->open_count = 1;
-	(*td)->changed = changed;
+	if (changed)
+		__set_thin_changed(*td);
 	(*td)->aborted_with_changes = false;
 	(*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks);
 	(*td)->transaction_id = le64_to_cpu(details_le.transaction_id);
@@ -1051,7 +1072,7 @@ static int __set_snapshot_details(struct dm_pool_metadata *pmd,
 	if (r)
 		return r;
 
-	td->changed = 1;
+	__set_thin_changed(td);
 	td->snapshotted_time = time;
 
 	snap->mapped_blocks = td->mapped_blocks;
@@ -1131,7 +1152,7 @@ int dm_pool_create_snap(struct dm_pool_metadata *pmd,
 	return r;
 }
 
-static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
+static int __delete_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
 {
 	int r;
 	uint64_t key = dev;
@@ -1158,6 +1179,8 @@ static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
 	if (r)
 		return r;
 
+	pmd->changed = true;
+
 	return 0;
 }
 
@@ -1168,7 +1191,7 @@ int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
 
 	down_write(&pmd->root_lock);
 	if (!pmd->fail_io)
-		r = __delete_device(pmd, dev);
+		r = __delete_thin(pmd, dev);
 	up_write(&pmd->root_lock);
 
 	return r;
@@ -1276,6 +1299,9 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd)
 	disk_super = dm_block_data(sblock);
 	disk_super->held_root = cpu_to_le64(held_root);
 	dm_bm_unlock(sblock);
+
+	pmd->changed = true;
+
 	return 0;
 }
 
@@ -1324,6 +1350,8 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd)
 
 	dm_tm_unlock(pmd->tm, copy);
 
+	pmd->changed = true;
+
 	return 0;
 }
 
@@ -1558,7 +1586,7 @@ static int __insert(struct dm_thin_device *td, dm_block_t block,
 	if (r)
 		return r;
 
-	td->changed = 1;
+	__set_thin_changed(td);
 	if (inserted)
 		td->mapped_blocks++;
 
@@ -1589,7 +1617,7 @@ static int __remove(struct dm_thin_device *td, dm_block_t block)
 		return r;
 
 	td->mapped_blocks--;
-	td->changed = 1;
+	__set_thin_changed(td);
 
 	return 0;
 }
@@ -1643,7 +1671,7 @@ static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_
 	}
 
 	td->mapped_blocks -= total_count;
-	td->changed = 1;
+	__set_thin_changed(td);
 
 	/*
 	 * Reinsert the mapping tree.
@@ -1735,16 +1763,10 @@ bool dm_thin_changed_this_transaction(struct dm_thin_device *td)
 
 bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd)
 {
-	bool r = false;
-	struct dm_thin_device *td, *tmp;
+	bool r;
 
 	down_read(&pmd->root_lock);
-	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
-		if (td->changed) {
-			r = td->changed;
-			break;
-		}
-	}
+	r = pmd->changed;
 	up_read(&pmd->root_lock);
 
 	return r;
@@ -1782,7 +1804,7 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
 		goto out;
 
 	r = __commit_transaction(pmd);
-	if (r <= 0)
+	if (r < 0)
 		goto out;
 
 	/*
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] dm thin metadata: check __commit_transaction()'s return
  2019-04-15 21:17 [PATCH 0/3] dm thin metadata: handful of improvements Mike Snitzer
  2019-04-15 21:17 ` [PATCH 1/3] dm space map common: zero entire ll_disk Mike Snitzer
  2019-04-15 21:17 ` [PATCH 2/3] dm thin metadata: do not write metadata if no changes occurred Mike Snitzer
@ 2019-04-15 21:17 ` Mike Snitzer
  2 siblings, 0 replies; 6+ messages in thread
From: Mike Snitzer @ 2019-04-15 21:17 UTC (permalink / raw)
  To: dm-devel; +Cc: ejt

Fix __reserve_metadata_snap() to return early if __commit_transaction()
fails.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/dm-thin-metadata.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index f4e8327abc75..3ba27f5f7da9 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1248,7 +1248,12 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd)
 	 * We commit to ensure the btree roots which we increment in a
 	 * moment are up to date.
 	 */
-	__commit_transaction(pmd);
+	r = __commit_transaction(pmd);
+	if (r < 0) {
+		DMWARN("%s: __commit_transaction() failed, error = %d",
+		       __func__, r);
+		return r;
+	}
 
 	/*
 	 * Copy the superblock.
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] dm thin metadata: do not write metadata if no changes occurred
  2019-04-15 21:17 ` [PATCH 2/3] dm thin metadata: do not write metadata if no changes occurred Mike Snitzer
@ 2019-04-16  2:39   ` Mike Snitzer
  2019-04-17  1:30     ` [PATCH v2 " Mike Snitzer
  0 siblings, 1 reply; 6+ messages in thread
From: Mike Snitzer @ 2019-04-16  2:39 UTC (permalink / raw)
  To: dm-devel; +Cc: ejt

On Mon, Apr 15 2019 at  5:17pm -0400,
Mike Snitzer <snitzer@redhat.com> wrote:

> Otherwise, just loading a thin-pool and then removing it will cause its
> metadata to be changed (e.g. superblock written) -- even without any
> thin devices being made active or metadata snapshot being manipulated.
> 
> Add 'changed' flag to struct dm_pool_metadata.  Set both td->changed and
> pmd->changed using __set_thin_changed() -- this assures pmd->changed is
> always set when td->changed is.  For methods that don't involve changing
> a td, set pmd->changed directly.
> 
> Rename __delete_device() to __delete_thin() -- improves symmetry with
> __create_thin().
> 
> Update dm_pool_changed_this_transaction() to simply return pmd->changed.
> 
> Fix dm_pool_commit_metadata() to open the next transaction if the return
> from __commit_transaction() is 0.  Not seeing why the early return ever
> made since for a return of 0 given that dm-io's async_io(), as used by
> bufio, always returns 0.

This v1 patch was incomplete.  However this approach's need to establish
pmd->changed everywhere that alters metadata, without doing so in terms
of a thin device, is like whack-a-mole.

But I think this could be simplified to only set a 'pmd->accessed'
(never clear it) and only__commit_transaction() if pmd->accessed --
so only pool messages that change metadata would need to set
pmd->accessed.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 2/3] dm thin metadata: do not write metadata if no changes occurred
  2019-04-16  2:39   ` Mike Snitzer
@ 2019-04-17  1:30     ` Mike Snitzer
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Snitzer @ 2019-04-17  1:30 UTC (permalink / raw)
  To: dm-devel; +Cc: ejt

Otherwise, just loading a thin-pool and then removing it will cause its
metadata to be changed (e.g. superblock written) -- even without any
thin devices being made active or metadata snapshot being manipulated.

Add 'in_service' flag to struct dm_pool_metadata and use a new
dm_pool_set_in_service() interface to set it if either a thin device is
activated or a message is sent to the thin-pool.  Once 'in_service' is
set it is never cleared.  __commit_transaction() will return 0 if
'in_service' is not set.

Also fix dm_pool_commit_metadata() to open the next transaction if the
return from __commit_transaction() is 0.  Not seeing why the early
return ever made since for a return of 0 given that dm-io's async_io(),
as used by bufio, always returns 0.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/dm-thin-metadata.c | 23 ++++++++++++++++++++++-
 drivers/md/dm-thin-metadata.h |  2 ++
 drivers/md/dm-thin.c          |  9 +++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 7381e477a945..fcff30fc07cd 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -201,6 +201,13 @@ struct dm_pool_metadata {
 	 */
 	bool fail_io:1;
 
+	/*
+	 * Set once a thin-pool has been accessed through one of the interfaces
+	 * that imply the pool is in-service (e.g. thin devices created/deleted,
+	 * thin-pool message, metadata snapshots, etc).
+	 */
+	bool in_service:1;
+
 	/*
 	 * Reading the space map roots can fail, so we read it into these
 	 * buffers before the superblock is locked and updated.
@@ -790,6 +797,9 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
 	 */
 	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
 
+	if (unlikely(!pmd->in_service))
+		return 0;
+
 	r = __write_changed_details(pmd);
 	if (r < 0)
 		return r;
@@ -853,6 +863,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
 	pmd->time = 0;
 	INIT_LIST_HEAD(&pmd->thin_devices);
 	pmd->fail_io = false;
+	pmd->in_service = false;
 	pmd->bdev = bdev;
 	pmd->data_block_size = data_block_size;
 
@@ -1727,6 +1738,16 @@ int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_
 	return r;
 }
 
+void dm_pool_set_in_service(struct dm_pool_metadata *pmd)
+{
+	if (!pmd->in_service) {
+		down_write(&pmd->root_lock);
+		if (!pmd->in_service)
+			pmd->in_service = true;
+		up_write(&pmd->root_lock);
+	}
+}
+
 bool dm_thin_changed_this_transaction(struct dm_thin_device *td)
 {
 	int r;
@@ -1787,7 +1808,7 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
 		goto out;
 
 	r = __commit_transaction(pmd);
-	if (r <= 0)
+	if (r < 0)
 		goto out;
 
 	/*
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index f6be0d733c20..8192530984be 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -47,6 +47,8 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
 
 int dm_pool_metadata_close(struct dm_pool_metadata *pmd);
 
+void dm_pool_set_in_service(struct dm_pool_metadata *pmd);
+
 /*
  * Compat feature flags.  Any incompat flags beyond the ones
  * specified below will prevent use of the thin metadata.
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index fcd887703f95..b6dbbdfc9118 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3822,6 +3822,13 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv,
 		return -EOPNOTSUPP;
 	}
 
+	/*
+	 * Any message sent to a thin-pool warrants putting it in-service
+	 * (even if the message is malformed, it speaks to a user
+	 *  attempting to interface with the thin-pool)
+	 */
+	dm_pool_set_in_service(pool->pmd);
+
 	if (!strcasecmp(argv[0], "create_thin"))
 		r = process_create_thin_mesg(argc, argv, pool);
 
@@ -4222,6 +4229,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 		goto bad_pool;
 	}
 
+	dm_pool_set_in_service(tc->pool->pmd);
+
 	r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td);
 	if (r) {
 		ti->error = "Couldn't open thin internal device";
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-04-17  1:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-04-15 21:17 [PATCH 0/3] dm thin metadata: handful of improvements Mike Snitzer
2019-04-15 21:17 ` [PATCH 1/3] dm space map common: zero entire ll_disk Mike Snitzer
2019-04-15 21:17 ` [PATCH 2/3] dm thin metadata: do not write metadata if no changes occurred Mike Snitzer
2019-04-16  2:39   ` Mike Snitzer
2019-04-17  1:30     ` [PATCH v2 " Mike Snitzer
2019-04-15 21:17 ` [PATCH 3/3] dm thin metadata: check __commit_transaction()'s return Mike Snitzer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.