All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10
@ 2016-11-18 22:26 Bart Van Assche
  2016-11-18 22:26 ` [PATCH 01/14] dm: Verify suspend_locking assumptions at runtime Bart Van Assche
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:26 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Hello Mike,

The fourteen patches in this series is what I came up with while 
reviewing and testing the device mapper kernel code. Compared to version 
1 one patch has been left out and several other patches have been added. 
The commit message of several patches that had already been posted has 
been updated with the feedback I received on the dm-devel mailing list. 
It would be appreciated if these patches would be considered for 
inclusion in the upstream kernel.

Thanks,

Bart.

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

* [PATCH 01/14] dm: Verify suspend_locking assumptions at runtime
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
@ 2016-11-18 22:26 ` Bart Van Assche
  2016-11-18 22:26 ` [PATCH 02/14] dm: Use blk_set_queue_dying() in __dm_destroy() Bart Van Assche
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:26 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Ensure that the assumptions about the caller holding suspend_lock
are checked at runtime if lockdep is enabled.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-table.c | 4 ++++
 drivers/md/dm.c       | 9 ++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index c4b53b3..49893fdc 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1654,6 +1654,8 @@ static void suspend_targets(struct dm_table *t, enum suspend_mode mode)
 	int i = t->num_targets;
 	struct dm_target *ti = t->targets;
 
+	lockdep_assert_held(&t->md->suspend_lock);
+
 	while (i--) {
 		switch (mode) {
 		case PRESUSPEND:
@@ -1701,6 +1703,8 @@ int dm_table_resume_targets(struct dm_table *t)
 {
 	int i, r = 0;
 
+	lockdep_assert_held(&t->md->suspend_lock);
+
 	for (i = 0; i < t->num_targets; i++) {
 		struct dm_target *ti = t->targets + i;
 
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ef7bf1d..49c4d00 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1628,11 +1628,10 @@ static void event_callback(void *context)
 	wake_up(&md->eventq);
 }
 
-/*
- * Protected by md->suspend_lock obtained by dm_swap_table().
- */
 static void __set_size(struct mapped_device *md, sector_t size)
 {
+	lockdep_assert_held(&md->suspend_lock);
+
 	set_capacity(md->disk, size);
 
 	i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
@@ -2084,8 +2083,6 @@ static void unlock_fs(struct mapped_device *md)
  * If __dm_suspend returns 0, the device is completely quiescent
  * now. There is no request-processing activity. All new requests
  * are being added to md->deferred list.
- *
- * Caller must hold md->suspend_lock
  */
 static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
 			unsigned suspend_flags, long task_state,
@@ -2301,6 +2298,8 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
 {
 	struct dm_table *map = NULL;
 
+	lockdep_assert_held(&md->suspend_lock);
+
 	if (md->internal_suspend_count++)
 		return; /* nested internal suspend */
 
-- 
2.10.1

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

* [PATCH 02/14] dm: Use blk_set_queue_dying() in __dm_destroy()
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
  2016-11-18 22:26 ` [PATCH 01/14] dm: Verify suspend_locking assumptions at runtime Bart Van Assche
@ 2016-11-18 22:26 ` Bart Van Assche
  2016-11-18 22:27 ` [PATCH 03/14] dm: Fix a race condition in rq_completed() Bart Van Assche
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:26 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

After QUEUE_FLAG_DYING has been set any code that is waiting in
get_request() should be woken up. Hence call blk_set_queue_dying()
instead of only setting QUEUE_FLAG_DYING.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 49c4d00..d19c372 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1885,9 +1885,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
 	set_bit(DMF_FREEING, &md->flags);
 	spin_unlock(&_minor_lock);
 
-	spin_lock_irq(q->queue_lock);
-	queue_flag_set(QUEUE_FLAG_DYING, q);
-	spin_unlock_irq(q->queue_lock);
+	blk_set_queue_dying(q);
 
 	if (dm_request_based(md) && md->kworker_task)
 		kthread_flush_worker(&md->kworker);
-- 
2.10.1

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

* [PATCH 03/14] dm: Fix a race condition in rq_completed()
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
  2016-11-18 22:26 ` [PATCH 01/14] dm: Verify suspend_locking assumptions at runtime Bart Van Assche
  2016-11-18 22:26 ` [PATCH 02/14] dm: Use blk_set_queue_dying() in __dm_destroy() Bart Van Assche
@ 2016-11-18 22:27 ` Bart Van Assche
  2016-11-18 22:27 ` [PATCH 04/14] dm: Simplify dm_table_determine_type() Bart Van Assche
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:27 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

It is required to hold the queue lock when calling blk_run_queue_async()
to avoid that a race between blk_run_queue_async() and
blk_cleanup_queue() is triggered.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-rq.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index f9f37ad..7df7948 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -210,6 +210,9 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig)
  */
 static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
 {
+	struct request_queue *q = md->queue;
+	unsigned long flags;
+
 	atomic_dec(&md->pending[rw]);
 
 	/* nudge anyone waiting on suspend queue */
@@ -222,8 +225,11 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
 	 * back into ->request_fn() could deadlock attempting to grab the
 	 * queue lock again.
 	 */
-	if (!md->queue->mq_ops && run_queue)
-		blk_run_queue_async(md->queue);
+	if (!q->mq_ops && run_queue) {
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_run_queue_async(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+	}
 
 	/*
 	 * dm_put() must be at the end of this function. See the comment above
-- 
2.10.1

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

* [PATCH 04/14] dm: Simplify dm_table_determine_type()
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (2 preceding siblings ...)
  2016-11-18 22:27 ` [PATCH 03/14] dm: Fix a race condition in rq_completed() Bart Van Assche
@ 2016-11-18 22:27 ` Bart Van Assche
  2016-11-18 22:27 ` [PATCH 05/14] dm: Simplify use_blk_mq initialization Bart Van Assche
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:27 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Use a single loop instead of two loops to determine whether or not
all_blk_mq has to be set.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-table.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 49893fdc..991d514 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -871,7 +871,7 @@ static int dm_table_determine_type(struct dm_table *t)
 {
 	unsigned i;
 	unsigned bio_based = 0, request_based = 0, hybrid = 0;
-	bool verify_blk_mq = false;
+	unsigned sq_count = 0, mq_count = 0;
 	struct dm_target *tgt;
 	struct dm_dev_internal *dd;
 	struct list_head *devices = dm_table_get_devices(t);
@@ -959,20 +959,15 @@ static int dm_table_determine_type(struct dm_table *t)
 		}
 
 		if (q->mq_ops)
-			verify_blk_mq = true;
+			mq_count++;
+		else
+			sq_count++;
 	}
-
-	if (verify_blk_mq) {
-		/* verify _all_ devices in the table are blk-mq devices */
-		list_for_each_entry(dd, devices, list)
-			if (!bdev_get_queue(dd->dm_dev->bdev)->mq_ops) {
-				DMERR("table load rejected: not all devices"
-				      " are blk-mq request-stackable");
-				return -EINVAL;
-			}
-
-		t->all_blk_mq = true;
+	if (sq_count && mq_count) {
+		DMERR("table load rejected: not all devices are blk-mq request-stackable");
+		return -EINVAL;
 	}
+	t->all_blk_mq = mq_count > 0;
 
 	return 0;
 }
-- 
2.10.1

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

* [PATCH 05/14] dm: Simplify use_blk_mq initialization
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (3 preceding siblings ...)
  2016-11-18 22:27 ` [PATCH 04/14] dm: Simplify dm_table_determine_type() Bart Van Assche
@ 2016-11-18 22:27 ` Bart Van Assche
  2016-11-18 22:28 ` [PATCH 06/14] dm-ioctl: Use offsetof() instead of open-coding it Bart Van Assche
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:27 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Use a single statement to declare and initialize 'use_blk_mq' instead
of two statements.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-rq.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index 7df7948..12ed327 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -23,11 +23,7 @@ static unsigned dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH;
 #define RESERVED_REQUEST_BASED_IOS	256
 static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
 
-#ifdef CONFIG_DM_MQ_DEFAULT
-static bool use_blk_mq = true;
-#else
-static bool use_blk_mq = false;
-#endif
+static bool use_blk_mq = IS_ENABLED(CONFIG_DM_MQ_DEFAULT);
 
 bool dm_use_blk_mq_default(void)
 {
-- 
2.10.1

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

* [PATCH 06/14] dm-ioctl: Use offsetof() instead of open-coding it
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (4 preceding siblings ...)
  2016-11-18 22:27 ` [PATCH 05/14] dm: Simplify use_blk_mq initialization Bart Van Assche
@ 2016-11-18 22:28 ` Bart Van Assche
  2016-11-18 22:28 ` [PATCH 07/14] dm, persistence: Remove an unused argument from dm_block_manager_create() Bart Van Assche
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:28 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Subtracting sizes is a fragile approach because the result is only
correct if the compiler has not added any padding at the end of the
structure. Hence use offsetof() instead of size subtraction. An
additional advantage of offsetof() is that it makes the intent more
clear.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-ioctl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 966eb4b..c72a770 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1697,7 +1697,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
 {
 	struct dm_ioctl *dmi;
 	int secure_data;
-	const size_t minimum_data_size = sizeof(*param_kernel) - sizeof(param_kernel->data);
+	const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
 
 	if (copy_from_user(param_kernel, user, minimum_data_size))
 		return -EFAULT;
-- 
2.10.1

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

* [PATCH 07/14] dm, persistence: Remove an unused argument from dm_block_manager_create()
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (5 preceding siblings ...)
  2016-11-18 22:28 ` [PATCH 06/14] dm-ioctl: Use offsetof() instead of open-coding it Bart Van Assche
@ 2016-11-18 22:28 ` Bart Van Assche
  2016-11-18 22:28 ` [PATCH 08/14] dm, persistence: Remove a dead assignment Bart Van Assche
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:28 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

The 'cache_size' argument of dm_block_manager_create() has never
been used. Hence remove it and also the definitions of the constants
passed as 'cache_size' argument.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-cache-metadata.c                | 3 ---
 drivers/md/dm-era-target.c                    | 2 --
 drivers/md/dm-thin-metadata.c                 | 2 --
 drivers/md/persistent-data/dm-block-manager.c | 1 -
 drivers/md/persistent-data/dm-block-manager.h | 2 +-
 5 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 6955778..d459999 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -27,8 +27,6 @@
 #define MIN_CACHE_VERSION 1
 #define MAX_CACHE_VERSION 1
 
-#define CACHE_METADATA_CACHE_SIZE 64
-
 /*
  *  3 for btree insert +
  *  2 for btree lookup used within space map
@@ -504,7 +502,6 @@ static int __create_persistent_data_objects(struct dm_cache_metadata *cmd,
 {
 	int r;
 	cmd->bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
-					  CACHE_METADATA_CACHE_SIZE,
 					  CACHE_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(cmd->bm)) {
 		DMERR("could not create block manager");
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index bf2b267..77f0b4e 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -254,7 +254,6 @@ static struct dm_block_validator sb_validator = {
  * Low level metadata handling
  *--------------------------------------------------------------*/
 #define DM_ERA_METADATA_BLOCK_SIZE 4096
-#define DM_ERA_METADATA_CACHE_SIZE 64
 #define ERA_MAX_CONCURRENT_LOCKS 5
 
 struct era_metadata {
@@ -615,7 +614,6 @@ static int create_persistent_data_objects(struct era_metadata *md,
 	int r;
 
 	md->bm = dm_block_manager_create(md->bdev, DM_ERA_METADATA_BLOCK_SIZE,
-					 DM_ERA_METADATA_CACHE_SIZE,
 					 ERA_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(md->bm)) {
 		DMERR("could not create block manager");
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index a15091a..0f0251d 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -77,7 +77,6 @@
 #define THIN_SUPERBLOCK_MAGIC 27022010
 #define THIN_SUPERBLOCK_LOCATION 0
 #define THIN_VERSION 2
-#define THIN_METADATA_CACHE_SIZE 64
 #define SECTOR_TO_BLOCK_SHIFT 3
 
 /*
@@ -686,7 +685,6 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f
 	int r;
 
 	pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
-					  THIN_METADATA_CACHE_SIZE,
 					  THIN_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(pmd->bm)) {
 		DMERR("could not create block manager");
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 1e33dd5..4aea053 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -360,7 +360,6 @@ struct dm_block_manager {
 
 struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
 						 unsigned block_size,
-						 unsigned cache_size,
 						 unsigned max_held_per_thread)
 {
 	int r;
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
index 3627d1b..e728937 100644
--- a/drivers/md/persistent-data/dm-block-manager.h
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -33,7 +33,7 @@ void *dm_block_data(struct dm_block *b);
 struct dm_block_manager;
 struct dm_block_manager *dm_block_manager_create(
 	struct block_device *bdev, unsigned block_size,
-	unsigned cache_size, unsigned max_held_per_thread);
+	unsigned max_held_per_thread);
 void dm_block_manager_destroy(struct dm_block_manager *bm);
 
 unsigned dm_bm_block_size(struct dm_block_manager *bm);
-- 
2.10.1

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

* [PATCH 08/14] dm, persistence: Remove a dead assignment
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (6 preceding siblings ...)
  2016-11-18 22:28 ` [PATCH 07/14] dm, persistence: Remove an unused argument from dm_block_manager_create() Bart Van Assche
@ 2016-11-18 22:28 ` Bart Van Assche
  2016-11-18 22:28 ` [PATCH 09/14] dm-mpath: Verify 'm->lock' locking assumptions at runtime Bart Van Assche
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:28 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

A value is assigned to 'nr_entries' but is never used. Hence remove
that variable.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/persistent-data/dm-array.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c
index e83047c..7938cd2 100644
--- a/drivers/md/persistent-data/dm-array.c
+++ b/drivers/md/persistent-data/dm-array.c
@@ -700,13 +700,11 @@ static int populate_ablock_with_values(struct dm_array_info *info, struct array_
 {
 	int r;
 	unsigned i;
-	uint32_t nr_entries;
 	struct dm_btree_value_type *vt = &info->value_type;
 
 	BUG_ON(le32_to_cpu(ab->nr_entries));
 	BUG_ON(new_nr > le32_to_cpu(ab->max_entries));
 
-	nr_entries = le32_to_cpu(ab->nr_entries);
 	for (i = 0; i < new_nr; i++) {
 		r = fn(base + i, element_at(info, ab, i), context);
 		if (r)
-- 
2.10.1

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

* [PATCH 09/14] dm-mpath: Verify 'm->lock' locking assumptions at runtime
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (7 preceding siblings ...)
  2016-11-18 22:28 ` [PATCH 08/14] dm, persistence: Remove a dead assignment Bart Van Assche
@ 2016-11-18 22:28 ` Bart Van Assche
  2016-11-18 22:29 ` [PATCH 10/14] dm-mpath: Change return type of pg_init_all_paths() from int into void Bart Van Assche
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:28 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Verify at runtime that __pg_init_all_paths() is called with
multipath.lock held if lockdep is enabled.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-mpath.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index e477af8..f1e226d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -348,6 +348,8 @@ static int __pg_init_all_paths(struct multipath *m)
 	struct pgpath *pgpath;
 	unsigned long pg_init_delay = 0;
 
+	lockdep_assert_held(&m->lock);
+
 	if (atomic_read(&m->pg_init_in_progress) || test_bit(MPATHF_PG_INIT_DISABLED, &m->flags))
 		return 0;
 
-- 
2.10.1

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

* [PATCH 10/14] dm-mpath: Change return type of pg_init_all_paths() from int into void
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (8 preceding siblings ...)
  2016-11-18 22:28 ` [PATCH 09/14] dm-mpath: Verify 'm->lock' locking assumptions at runtime Bart Van Assche
@ 2016-11-18 22:29 ` Bart Van Assche
  2016-11-18 22:29 ` [PATCH 11/14] dm-mpath: Do not touch *__clone if request allocation fails Bart Van Assche
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:29 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

None of the callers of pg_init_all_paths() check its return value.
Hence change the return type of pg_init_all_paths() from int into
void.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-mpath.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index f1e226d..1c97f0e 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -374,16 +374,13 @@ static int __pg_init_all_paths(struct multipath *m)
 	return atomic_read(&m->pg_init_in_progress);
 }
 
-static int pg_init_all_paths(struct multipath *m)
+static void pg_init_all_paths(struct multipath *m)
 {
-	int r;
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
-	r = __pg_init_all_paths(m);
+	__pg_init_all_paths(m);
 	spin_unlock_irqrestore(&m->lock, flags);
-
-	return r;
 }
 
 static void __switch_pg(struct multipath *m, struct priority_group *pg)
-- 
2.10.1

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

* [PATCH 11/14] dm-mpath: Do not touch *__clone if request allocation fails
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (9 preceding siblings ...)
  2016-11-18 22:29 ` [PATCH 10/14] dm-mpath: Change return type of pg_init_all_paths() from int into void Bart Van Assche
@ 2016-11-18 22:29 ` Bart Van Assche
  2016-11-18 22:29 ` [PATCH 12/14] dm-mpath: Micro-optimize the hot path Bart Van Assche
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:29 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Do not modify *__clone if blk_mq_alloc_request() fails. This makes
it easier to figure out what is going on if the caller accidentally
dereferences *__clone if blk_mq_alloc_request() failed.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-mpath.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1c97f0e..5c73818 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -582,16 +582,17 @@ static int __multipath_map(struct dm_target *ti, struct request *clone,
 		 * .request_fn stacked on blk-mq path(s) and
 		 * blk-mq stacked on blk-mq path(s).
 		 */
-		*__clone = blk_mq_alloc_request(bdev_get_queue(bdev),
-						rq_data_dir(rq), BLK_MQ_REQ_NOWAIT);
-		if (IS_ERR(*__clone)) {
-			/* ENOMEM, requeue */
+		clone = blk_mq_alloc_request(bdev_get_queue(bdev),
+					rq_data_dir(rq), BLK_MQ_REQ_NOWAIT);
+		if (IS_ERR(clone)) {
+			/* EBUSY, ENODEV or EWOULDBLOCK; requeue */
 			clear_request_fn_mpio(m, map_context);
 			return r;
 		}
-		(*__clone)->bio = (*__clone)->biotail = NULL;
-		(*__clone)->rq_disk = bdev->bd_disk;
-		(*__clone)->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+		*__clone = clone;
+		clone->bio = clone->biotail = NULL;
+		clone->rq_disk = bdev->bd_disk;
+		clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
 	}
 
 	if (pgpath->pg->ps.type->start_io)
-- 
2.10.1

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

* [PATCH 12/14] dm-mpath: Micro-optimize the hot path
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (10 preceding siblings ...)
  2016-11-18 22:29 ` [PATCH 11/14] dm-mpath: Do not touch *__clone if request allocation fails Bart Van Assche
@ 2016-11-18 22:29 ` Bart Van Assche
  2016-11-18 22:29 ` [PATCH 13/14] dm-mpath: Introduce assign_bit() Bart Van Assche
  2016-11-18 22:30 ` [PATCH 14/14] dm, dm-mpath: Make it easier to detect unintended I/O request flushes Bart Van Assche
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:29 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

Instead of checking MPATHF_QUEUE_IF_NO_PATH,
MPATHF_SAVED_QUEUE_IF_NO_PATH and the no_flush flag to decide whether
or not to push back a request if there are no paths available, only
clear MPATHF_QUEUE_IF_NO_PATH in queue_if_no_path() if no_flush has
not been set. The result is that only a single bit has to be tested
in the hot path to decide whether or not a request must be pushed
back and also that m->lock does not have to be taken in the hot path.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-mpath.c | 70 ++++++++-------------------------------------------
 1 file changed, 11 insertions(+), 59 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5c73818..fff5d12 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -489,47 +489,6 @@ static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes)
 }
 
 /*
- * Check whether bios must be queued in the device-mapper core rather
- * than here in the target.
- *
- * If m->queue_if_no_path and m->saved_queue_if_no_path hold the
- * same value then we are not between multipath_presuspend()
- * and multipath_resume() calls and we have no need to check
- * for the DMF_NOFLUSH_SUSPENDING flag.
- */
-static bool __must_push_back(struct multipath *m)
-{
-	return ((test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) !=
-		 test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags)) &&
-		dm_noflush_suspending(m->ti));
-}
-
-static bool must_push_back_rq(struct multipath *m)
-{
-	bool r;
-	unsigned long flags;
-
-	spin_lock_irqsave(&m->lock, flags);
-	r = (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
-	     __must_push_back(m));
-	spin_unlock_irqrestore(&m->lock, flags);
-
-	return r;
-}
-
-static bool must_push_back_bio(struct multipath *m)
-{
-	bool r;
-	unsigned long flags;
-
-	spin_lock_irqsave(&m->lock, flags);
-	r = __must_push_back(m);
-	spin_unlock_irqrestore(&m->lock, flags);
-
-	return r;
-}
-
-/*
  * Map cloned requests (request-based multipath)
  */
 static int __multipath_map(struct dm_target *ti, struct request *clone,
@@ -549,7 +508,7 @@ static int __multipath_map(struct dm_target *ti, struct request *clone,
 		pgpath = choose_pgpath(m, nr_bytes);
 
 	if (!pgpath) {
-		if (must_push_back_rq(m))
+		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
 			return DM_MAPIO_DELAY_REQUEUE;
 		return -EIO;	/* Failed */
 	} else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
@@ -651,9 +610,9 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
 	}
 
 	if (!pgpath) {
-		if (!must_push_back_bio(m))
-			return -EIO;
-		return DM_MAPIO_REQUEUE;
+		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
+			return DM_MAPIO_REQUEUE;
+		return -EIO;
 	}
 
 	mpio->pgpath = pgpath;
@@ -745,7 +704,7 @@ static int queue_if_no_path(struct multipath *m, bool queue_if_no_path,
 		else
 			clear_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
 	}
-	if (queue_if_no_path)
+	if (queue_if_no_path || dm_noflush_suspending(m->ti))
 		set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
 	else
 		clear_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
@@ -1578,12 +1537,9 @@ static int do_end_io(struct multipath *m, struct request *clone,
 	if (mpio->pgpath)
 		fail_path(mpio->pgpath);
 
-	if (!atomic_read(&m->nr_valid_paths)) {
-		if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-			if (!must_push_back_rq(m))
-				r = -EIO;
-		}
-	}
+	if (atomic_read(&m->nr_valid_paths) == 0 &&
+	    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
+		r = -EIO;
 
 	return r;
 }
@@ -1625,13 +1581,9 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
 	if (mpio->pgpath)
 		fail_path(mpio->pgpath);
 
-	if (!atomic_read(&m->nr_valid_paths)) {
-		if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-			if (!must_push_back_bio(m))
-				return -EIO;
-			return DM_ENDIO_REQUEUE;
-		}
-	}
+	if (atomic_read(&m->nr_valid_paths) == 0 &&
+	    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
+		return -EIO;
 
 	/* Queue for the daemon to resubmit */
 	dm_bio_restore(get_bio_details_from_bio(clone), clone);
-- 
2.10.1

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

* [PATCH 13/14] dm-mpath: Introduce assign_bit()
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (11 preceding siblings ...)
  2016-11-18 22:29 ` [PATCH 12/14] dm-mpath: Micro-optimize the hot path Bart Van Assche
@ 2016-11-18 22:29 ` Bart Van Assche
  2016-11-18 22:30 ` [PATCH 14/14] dm, dm-mpath: Make it easier to detect unintended I/O request flushes Bart Van Assche
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:29 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

This patch does not change any functionality but makes the code
easier to read.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-mpath.c | 37 ++++++++++++++++---------------------
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index fff5d12..4a3afec 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -683,6 +683,14 @@ static void process_queued_bios(struct work_struct *work)
 	blk_finish_plug(&plug);
 }
 
+static void assign_bit(bool value, long nr, unsigned long *addr)
+{
+	if (value)
+		set_bit(nr, addr);
+	else
+		clear_bit(nr, addr);
+}
+
 /*
  * If we run out of usable paths, should we queue I/O or error it?
  */
@@ -692,23 +700,12 @@ static int queue_if_no_path(struct multipath *m, bool queue_if_no_path,
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
-
-	if (save_old_value) {
-		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
-			set_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
-		else
-			clear_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
-	} else {
-		if (queue_if_no_path)
-			set_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
-		else
-			clear_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
-	}
-	if (queue_if_no_path || dm_noflush_suspending(m->ti))
-		set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
-	else
-		clear_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
-
+	assign_bit((save_old_value &&
+		    test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) ||
+		   (!save_old_value && queue_if_no_path),
+		   MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags);
+	assign_bit(queue_if_no_path || dm_noflush_suspending(m->ti),
+		   MPATHF_QUEUE_IF_NO_PATH, &m->flags);
 	spin_unlock_irqrestore(&m->lock, flags);
 
 	if (!queue_if_no_path) {
@@ -1649,10 +1646,8 @@ static void multipath_resume(struct dm_target *ti)
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
-	if (test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags))
-		set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
-	else
-		clear_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
+	assign_bit(test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags),
+		   MPATHF_QUEUE_IF_NO_PATH, &m->flags);
 	spin_unlock_irqrestore(&m->lock, flags);
 }
 
-- 
2.10.1

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

* [PATCH 14/14] dm, dm-mpath: Make it easier to detect unintended I/O request flushes
  2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
                   ` (12 preceding siblings ...)
  2016-11-18 22:29 ` [PATCH 13/14] dm-mpath: Introduce assign_bit() Bart Van Assche
@ 2016-11-18 22:30 ` Bart Van Assche
  13 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2016-11-18 22:30 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: device-mapper development

I/O errors triggered by multipathd incorrectly not enabling the
no-flush flag for DM_DEVICE_SUSPEND or DM_DEVICE_RESUME are hard to
debug. Add more logging to make it easier to debug this.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
 drivers/md/dm-mpath.c | 25 +++++++++++++++++++++----
 drivers/md/dm.c       |  3 +++
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 4a3afec..c3d7e3e 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -489,6 +489,23 @@ static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes)
 }
 
 /*
+ * Note: dm_report_eio() is a macro instead of a function to make pr_debug()
+ * report the function name and line number of the function from which it has
+ * been invoked.
+ */
+#define dm_report_eio(m)						\
+({									\
+	struct mapped_device *md = dm_table_get_md((m)->ti->table);	\
+									\
+	pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \
+		 dm_device_name(md),					\
+		 test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags),	\
+		 test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags),	\
+		 dm_noflush_suspending((m)->ti));			\
+	-EIO;								\
+})
+
+/*
  * Map cloned requests (request-based multipath)
  */
 static int __multipath_map(struct dm_target *ti, struct request *clone,
@@ -510,7 +527,7 @@ static int __multipath_map(struct dm_target *ti, struct request *clone,
 	if (!pgpath) {
 		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
 			return DM_MAPIO_DELAY_REQUEUE;
-		return -EIO;	/* Failed */
+		return dm_report_eio(m);	/* Failed */
 	} else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
 		   test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) {
 		pg_init_all_paths(m);
@@ -612,7 +629,7 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
 	if (!pgpath) {
 		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
 			return DM_MAPIO_REQUEUE;
-		return -EIO;
+		return dm_report_eio(m);
 	}
 
 	mpio->pgpath = pgpath;
@@ -1536,7 +1553,7 @@ static int do_end_io(struct multipath *m, struct request *clone,
 
 	if (atomic_read(&m->nr_valid_paths) == 0 &&
 	    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
-		r = -EIO;
+		r = dm_report_eio(m);
 
 	return r;
 }
@@ -1580,7 +1597,7 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
 
 	if (atomic_read(&m->nr_valid_paths) == 0 &&
 	    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
-		return -EIO;
+		return dm_report_eio(m);
 
 	/* Queue for the daemon to resubmit */
 	dm_bio_restore(get_bio_details_from_bio(clone), clone);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index d19c372..08a21d1 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2098,6 +2098,9 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
 	 */
 	if (noflush)
 		set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+	else
+		pr_debug("%s: suspending without no-flush flag\n",
+			 dm_device_name(md));
 
 	/*
 	 * This gets reverted if there's an error later and the targets
-- 
2.10.1

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

end of thread, other threads:[~2016-11-18 22:30 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-18 22:26 [PATCH v2 0/14] Device mapper patches for Linux kernel v4.10 Bart Van Assche
2016-11-18 22:26 ` [PATCH 01/14] dm: Verify suspend_locking assumptions at runtime Bart Van Assche
2016-11-18 22:26 ` [PATCH 02/14] dm: Use blk_set_queue_dying() in __dm_destroy() Bart Van Assche
2016-11-18 22:27 ` [PATCH 03/14] dm: Fix a race condition in rq_completed() Bart Van Assche
2016-11-18 22:27 ` [PATCH 04/14] dm: Simplify dm_table_determine_type() Bart Van Assche
2016-11-18 22:27 ` [PATCH 05/14] dm: Simplify use_blk_mq initialization Bart Van Assche
2016-11-18 22:28 ` [PATCH 06/14] dm-ioctl: Use offsetof() instead of open-coding it Bart Van Assche
2016-11-18 22:28 ` [PATCH 07/14] dm, persistence: Remove an unused argument from dm_block_manager_create() Bart Van Assche
2016-11-18 22:28 ` [PATCH 08/14] dm, persistence: Remove a dead assignment Bart Van Assche
2016-11-18 22:28 ` [PATCH 09/14] dm-mpath: Verify 'm->lock' locking assumptions at runtime Bart Van Assche
2016-11-18 22:29 ` [PATCH 10/14] dm-mpath: Change return type of pg_init_all_paths() from int into void Bart Van Assche
2016-11-18 22:29 ` [PATCH 11/14] dm-mpath: Do not touch *__clone if request allocation fails Bart Van Assche
2016-11-18 22:29 ` [PATCH 12/14] dm-mpath: Micro-optimize the hot path Bart Van Assche
2016-11-18 22:29 ` [PATCH 13/14] dm-mpath: Introduce assign_bit() Bart Van Assche
2016-11-18 22:30 ` [PATCH 14/14] dm, dm-mpath: Make it easier to detect unintended I/O request flushes Bart Van Assche

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.