Browse Source

Merge tag 'for-4.16/dm-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:

 - a stable DM multipath fix to restore ability to pass integrity data

 - two DM multipath fixes for a fix that was merged into 4.16-rc5

* tag 'for-4.16/dm-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm mpath: fix passing integrity data
  dm mpath: eliminate need to use scsi_device_from_queue
  dm mpath: fix uninitialized 'pg_init_wait' waitqueue_head NULL pointer
Linus Torvalds 7 years ago
parent
commit
667058ae60
1 changed files with 21 additions and 22 deletions
  1. 21 22
      drivers/md/dm-mpath.c

+ 21 - 22
drivers/md/dm-mpath.c

@@ -22,7 +22,6 @@
 #include <linux/time.h>
 #include <linux/time.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
-#include <scsi/scsi_device.h>
 #include <scsi/scsi_dh.h>
 #include <scsi/scsi_dh.h>
 #include <linux/atomic.h>
 #include <linux/atomic.h>
 #include <linux/blk-mq.h>
 #include <linux/blk-mq.h>
@@ -223,6 +222,16 @@ static int alloc_multipath_stage2(struct dm_target *ti, struct multipath *m)
 
 
 	dm_table_set_type(ti->table, m->queue_mode);
 	dm_table_set_type(ti->table, m->queue_mode);
 
 
+	/*
+	 * Init fields that are only used when a scsi_dh is attached
+	 * - must do this unconditionally (really doesn't hurt non-SCSI uses)
+	 */
+	set_bit(MPATHF_QUEUE_IO, &m->flags);
+	atomic_set(&m->pg_init_in_progress, 0);
+	atomic_set(&m->pg_init_count, 0);
+	m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
+	init_waitqueue_head(&m->pg_init_wait);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -331,7 +340,6 @@ static void __switch_pg(struct multipath *m, struct priority_group *pg)
 		set_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
 		set_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
 		set_bit(MPATHF_QUEUE_IO, &m->flags);
 		set_bit(MPATHF_QUEUE_IO, &m->flags);
 	} else {
 	} else {
-		/* FIXME: not needed if no scsi_dh is attached */
 		clear_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
 		clear_bit(MPATHF_PG_INIT_REQUIRED, &m->flags);
 		clear_bit(MPATHF_QUEUE_IO, &m->flags);
 		clear_bit(MPATHF_QUEUE_IO, &m->flags);
 	}
 	}
@@ -796,15 +804,14 @@ static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
 	return 0;
 	return 0;
 }
 }
 
 
-static int setup_scsi_dh(struct block_device *bdev, struct multipath *m, char **error)
+static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
+			 const char *attached_handler_name, char **error)
 {
 {
 	struct request_queue *q = bdev_get_queue(bdev);
 	struct request_queue *q = bdev_get_queue(bdev);
-	const char *attached_handler_name;
 	int r;
 	int r;
 
 
 	if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
 	if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
 retain:
 retain:
-		attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
 		if (attached_handler_name) {
 		if (attached_handler_name) {
 			/*
 			/*
 			 * Clear any hw_handler_params associated with a
 			 * Clear any hw_handler_params associated with a
@@ -823,16 +830,6 @@ retain:
 			 */
 			 */
 			kfree(m->hw_handler_name);
 			kfree(m->hw_handler_name);
 			m->hw_handler_name = attached_handler_name;
 			m->hw_handler_name = attached_handler_name;
-
-			/*
-			 * Init fields that are only used when a scsi_dh is attached
-			 */
-			if (!test_and_set_bit(MPATHF_QUEUE_IO, &m->flags)) {
-				atomic_set(&m->pg_init_in_progress, 0);
-				atomic_set(&m->pg_init_count, 0);
-				m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
-				init_waitqueue_head(&m->pg_init_wait);
-			}
 		}
 		}
 	}
 	}
 
 
@@ -868,7 +865,8 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 	int r;
 	int r;
 	struct pgpath *p;
 	struct pgpath *p;
 	struct multipath *m = ti->private;
 	struct multipath *m = ti->private;
-	struct scsi_device *sdev;
+	struct request_queue *q;
+	const char *attached_handler_name;
 
 
 	/* we need at least a path arg */
 	/* we need at least a path arg */
 	if (as->argc < 1) {
 	if (as->argc < 1) {
@@ -887,11 +885,11 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 		goto bad;
 		goto bad;
 	}
 	}
 
 
-	sdev = scsi_device_from_queue(bdev_get_queue(p->path.dev->bdev));
-	if (sdev) {
-		put_device(&sdev->sdev_gendev);
+	q = bdev_get_queue(p->path.dev->bdev);
+	attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
+	if (attached_handler_name) {
 		INIT_DELAYED_WORK(&p->activate_path, activate_path_work);
 		INIT_DELAYED_WORK(&p->activate_path, activate_path_work);
-		r = setup_scsi_dh(p->path.dev->bdev, m, &ti->error);
+		r = setup_scsi_dh(p->path.dev->bdev, m, attached_handler_name, &ti->error);
 		if (r) {
 		if (r) {
 			dm_put_device(ti, p->path.dev);
 			dm_put_device(ti, p->path.dev);
 			goto bad;
 			goto bad;
@@ -2022,8 +2020,9 @@ static int multipath_busy(struct dm_target *ti)
  *---------------------------------------------------------------*/
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
 static struct target_type multipath_target = {
 	.name = "multipath",
 	.name = "multipath",
-	.version = {1, 12, 0},
-	.features = DM_TARGET_SINGLETON | DM_TARGET_IMMUTABLE,
+	.version = {1, 13, 0},
+	.features = DM_TARGET_SINGLETON | DM_TARGET_IMMUTABLE |
+		    DM_TARGET_PASSES_INTEGRITY,
 	.module = THIS_MODULE,
 	.module = THIS_MODULE,
 	.ctr = multipath_ctr,
 	.ctr = multipath_ctr,
 	.dtr = multipath_dtr,
 	.dtr = multipath_dtr,