[dm-devel] RE: [PATCH] Handle multipath paths in a path group properly during pg_init

Moger, Babu Babu.Moger at lsi.com
Mon Mar 30 22:14:24 UTC 2009


Reviewed and Tested-by: Babu Moger <babu.moger at lsi.com>

> -----Original Message-----
> From: Chandra Seetharaman [mailto:sekharan at us.ibm.com]
> Sent: Monday, March 30, 2009 1:08 PM
> To: dm-devel
> Cc: Alasdair G Kergon; Moger, Babu; Hannes Reinecke; Mike Anderson
> Subject: [PATCH] Handle multipath paths in a path group properly during
> pg_init
> 
> Resending the patch to get in patchwork...
> -------
> The problem reported by Moger Babu was caused due to the architectural
> change made when we moved from dm hardware handler to SCSI hardware
> handler.
> 
> Thanks Babu for finding and reporting the bug.
> 
> All of the hardware handlers, do have a state now, and they are set to
> active and (some form of) inactive. All of them have prep_fn, which use
> this "state" to fail the I/O without it ever being sent to the device.
> 
> As Babu has noted in his email, the pg_init/activate is sent on only one
> path and the "state" of that path is changed appropriately to "active"
> while other paths in the same path group are never changed as they never
> got an "activate".
> 
> Attached is a patch (compiled, tested, but not clean yet), which makes
> changes in the dm-multipath layer to send an "activate" on each paths in
> the path groups.
> 
> Mike (Anderson) and I had a discussion about whether to implement this
> in the dm-mulitpath layer or in the SCSI hardware handler layer and we
> came to a conclusion that it is best suited to be in the dm-mulitpath
> layer as it is the one that knows the relationship between different
> paths.
> 
> If it were to be done at the Hardware handler layer, then the hardware
> handler may end up having a different notion of the path relationship
> and hence may not work as expected by the dm-multipath layer.
> 
> This patch has been tested by Hannes in EMC storage. Babu and I tested it
> in LSI storage.
> ----------
> 
> Signed-off-by: Chandra Seetharaman <sekharan at us.ibm.com>
> 
> ---
> Index: linux-2.6.29/drivers/md/dm-mpath.c
> ===================================================================
> --- linux-2.6.29.orig/drivers/md/dm-mpath.c
> +++ linux-2.6.29/drivers/md/dm-mpath.c
> @@ -36,6 +36,7 @@ struct pgpath {
> 
>  	struct dm_path path;
>  	struct work_struct deactivate_path;
> +	struct work_struct activate_path;
>  };
> 
>  #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
> @@ -65,8 +66,6 @@ struct multipath {
>  	spinlock_t lock;
> 
>  	const char *hw_handler_name;
> -	struct work_struct activate_path;
> -	struct pgpath *pgpath_to_activate;
>  	unsigned nr_priority_groups;
>  	struct list_head priority_groups;
>  	unsigned pg_init_required;	/* pg_init needs calling? */
> @@ -129,6 +128,7 @@ static struct pgpath *alloc_pgpath(void)
>  	if (pgpath) {
>  		pgpath->is_active = 1;
>  		INIT_WORK(&pgpath->deactivate_path, deactivate_path);
> +		INIT_WORK(&pgpath->activate_path, activate_path);
>  	}
> 
>  	return pgpath;
> @@ -170,10 +170,6 @@ static void free_pgpaths(struct list_hea
>  		if (m->hw_handler_name)
>  			scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
>  		dm_put_device(ti, pgpath->path.dev);
> -		spin_lock_irqsave(&m->lock, flags);
> -		if (m->pgpath_to_activate == pgpath)
> -			m->pgpath_to_activate = NULL;
> -		spin_unlock_irqrestore(&m->lock, flags);
>  		free_pgpath(pgpath);
>  	}
>  }
> @@ -203,7 +199,6 @@ static struct multipath *alloc_multipath
>  		m->queue_io = 1;
>  		INIT_WORK(&m->process_queued_ios, process_queued_ios);
>  		INIT_WORK(&m->trigger_event, trigger_event);
> -		INIT_WORK(&m->activate_path, activate_path);
>  		m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
>  		if (!m->mpio_pool) {
>  			kfree(m);
> @@ -428,8 +423,8 @@ static void process_queued_ios(struct wo
>  {
>  	struct multipath *m =
>  		container_of(work, struct multipath, process_queued_ios);
> -	struct pgpath *pgpath = NULL;
> -	unsigned init_required = 0, must_queue = 1;
> +	struct pgpath *pgpath = NULL, *tmp;
> +	unsigned must_queue = 1;
>  	unsigned long flags;
> 
>  	spin_lock_irqsave(&m->lock, flags);
> @@ -447,19 +442,15 @@ static void process_queued_ios(struct wo
>  		must_queue = 0;
> 
>  	if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
> -		m->pgpath_to_activate = pgpath;
>  		m->pg_init_count++;
>  		m->pg_init_required = 0;
> -		m->pg_init_in_progress = 1;
> -		init_required = 1;
> +		list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
> +			queue_work(kmpath_handlerd, &tmp->activate_path);
> +			m->pg_init_in_progress++;
> +		}
>  	}
> -
>  out:
>  	spin_unlock_irqrestore(&m->lock, flags);
> -
> -	if (init_required)
> -		queue_work(kmpath_handlerd, &m->activate_path);
> -
>  	if (!must_queue)
>  		dispatch_queued_ios(m);
>  }
> @@ -1111,27 +1102,20 @@ static void pg_init_done(struct dm_path
>  		pg->bypassed = 0;
>  	}
> 
> -	m->pg_init_in_progress = 0;
> -	queue_work(kmultipathd, &m->process_queued_ios);
> +	m->pg_init_in_progress--;
> +	if (!m->pg_init_in_progress)
> +		queue_work(kmultipathd, &m->process_queued_ios);
>  	spin_unlock_irqrestore(&m->lock, flags);
>  }
> 
>  static void activate_path(struct work_struct *work)
>  {
>  	int ret;
> -	struct multipath *m =
> -		container_of(work, struct multipath, activate_path);
> -	struct dm_path *path;
> -	unsigned long flags;
> +	struct pgpath *pgpath =
> +		container_of(work, struct pgpath, activate_path);
> 
> -	spin_lock_irqsave(&m->lock, flags);
> -	path = &m->pgpath_to_activate->path;
> -	m->pgpath_to_activate = NULL;
> -	spin_unlock_irqrestore(&m->lock, flags);
> -	if (!path)
> -		return;
> -	ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
> -	pg_init_done(path, ret);
> +	ret = scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev));
> +	pg_init_done(&pgpath->path, ret);
>  }
> 
>  /*
> 





More information about the dm-devel mailing list