All of lore.kernel.org
 help / color / mirror / Atom feed
* [2.6.22-rc1 PATCH] dm-hp-sw: HP Active/Passive hardware handler baseline
@ 2007-05-23 20:18 Dave Wysochanski
  2007-05-23 21:17 ` Mike Christie
  0 siblings, 1 reply; 3+ messages in thread
From: Dave Wysochanski @ 2007-05-23 20:18 UTC (permalink / raw)
  To: device-mapper development

Baseline support for HP Active / Passive arrays.
Possible enhancements include handling specific check conditions,
pg_init retries, and configurable timeouts.

Signed-off-by: Dave Wysochanski <dave.wysochanski@redhat.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

--

Index: linux-2.6.22-rc1/drivers/md/Makefile
===================================================================
--- linux-2.6.22-rc1.orig/drivers/md/Makefile
+++ linux-2.6.22-rc1/drivers/md/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_EMC)	+= dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_HP)	+= dm-hp-sw.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
Index: linux-2.6.22-rc1/drivers/md/dm-hp-sw.c
===================================================================
--- /dev/null
+++ linux-2.6.22-rc1/drivers/md/dm-hp-sw.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005 Mike Christie, All rights reserved.
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ * Authors: Mike Christie
+ *          Dave Wysochanski
+ *
+ * This file is released under the GPL.
+ *
+ * This module implements the specific path activation code for
+ * HP StorageWorks and FSC FibreCat Asymmetric (Active/Passive)
+ * storage arrays.
+ * These storage arrays have controller-based failover, not
+ * LUN-based failover.  However, LUN-based failover is the design
+ * of dm-multipath. Thus, this module is written for LUN-based failover.
+ */
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#define DM_MSG_PREFIX "multipath hp"
+
+struct hp_sw_context {
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+
+/**
+ * hp_sw_end_io - Completion handler for HP path activation.
+ * @req: failover request
+ * @error: scsi-ml error
+ *
+ *  Check sense data, free request structure, and notify dm that
+ *  pg initialization has completed.
+ *
+ * Context: scsi-ml softirq
+ *
+ * Possible optimizations
+ * 1. Actually check sense data for retryable error (e.g. NOT_READY)
+ */
+static void hp_sw_end_io(struct request *req, int error)
+{
+	struct dm_path *path = req->end_io_data;
+	unsigned err_flags;
+
+	if (!error) {
+		err_flags = 0;
+		DMDEBUG("hp_sw: path activation command on %s - success",
+		       	path->dev->name);
+	}
+	else {
+		DMWARN("hp_sw: path activation command on %s - error=0x%x",
+		       path->dev->name, error);
+		err_flags = MP_FAIL_PATH;
+	}
+
+	req->end_io_data = NULL;
+	__blk_put_request(req->q, req);
+	dm_pg_init_complete(path, err_flags);
+}
+
+/**
+ * hp_sw_get_request - Allocate an HP specific path activation request
+ * @path: path on which request will be sent (needed for request queue)
+ *
+ * The START command is used for path activation request.
+ * These arrays are controller-based failover, not LUN based.
+ * One START command issued to a single path will fail over all
+ * LUNs for the same controller.
+ *
+ * Possible optimizations
+ * 1. Make timeout configurable
+ * 2. Preallocate request
+ */
+static struct request *hp_sw_get_request(struct dm_path *path)
+{
+	struct request *req=NULL;
+	struct block_device *bdev = path->dev->bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
+	struct hp_sw_context *h = path->hwhcontext;
+
+	req = blk_get_request(q, WRITE, GFP_ATOMIC);
+	if (req == NULL)
+		goto exit;
+
+	req->timeout = 60*HZ;
+
+	req->errors = 0;
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
+	req->end_io = hp_sw_end_io;
+	req->end_io_data = path;
+	req->sense = h->sense;
+	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
+
+	memset(&req->cmd, 0, BLK_MAX_CDB);
+	req->cmd[0] = START_STOP;
+	req->cmd[4] = 1;
+	req->cmd_len = COMMAND_SIZE(req->cmd[0]);
+exit:
+	return req;
+}
+
+/**
+ * hp_sw_pg_init - HP path activation implementation.
+ * @hwh: hardware handler specific data
+ * @bypassed: unused; is the path group bypassed? (see dm-mpath.c)
+ * @path: path to send initialization command
+ *
+ * Send an HP-specific path activation command on 'path'.
+ * Do not try to optimize in any way, just send the activation command.
+ * More than one path activation command may be sent to the same controller.
+ * This seems to work fine for basic failover support.
+ *
+ * Possible optimizations
+ * 1. Detect an in-progress activation request and avoid submitting another one
+ * 2. Model the controller and only send a single activation request at a time
+ * 3. Determine the state of a path before sending an activation request
+ *
+ * Context: kmpathd (see process_queued_ios() in dm-mpath.c)
+ */
+static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
+			  struct dm_path *path)
+{
+	struct request *req;
+	struct hp_sw_context *h;
+	unsigned err_flags;
+
+	path->hwhcontext = hwh->context;
+	h = (struct hp_sw_context *) hwh->context;
+
+	req = hp_sw_get_request(path);
+	if (!req) {
+		DMERR("hp_sw: path activation command allocation fail on %s ",
+		      path->dev->name);
+		goto fail;
+	}
+
+	DMDEBUG("hp_sw: path activation command sent on %s",
+		path->dev->name);
+
+	elv_add_request(req->q, req, ELEVATOR_INSERT_FRONT, 1);
+	return;
+
+ fail:
+	err_flags = MP_FAIL_PATH;
+	dm_pg_init_complete(path, err_flags);
+}
+
+static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+	struct hp_sw_context *h;
+
+	h = kmalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+	hwh->context = h;
+	return 0;
+}
+
+static void hp_sw_destroy(struct hw_handler *hwh)
+{
+	struct hp_sw_context *h = hwh->context;
+
+	kfree(h);
+	hwh->context = NULL;
+}
+
+static struct hw_handler_type hp_sw_hwh = {
+	.name = "hp_sw",
+	.module = THIS_MODULE,
+	.create = hp_sw_create,
+	.destroy = hp_sw_destroy,
+	.pg_init = hp_sw_pg_init,
+};
+
+static int __init hp_sw_init(void)
+{
+	int r;
+
+	r = dm_register_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: register failed %d", r);
+
+	DMINFO("hp_sw version 0.0.1 loaded");
+
+	return r;
+}
+
+static void __exit hp_sw_exit(void)
+{
+	int r;
+
+	r = dm_unregister_hw_handler(&hp_sw_hwh);
+	if (r < 0)
+		DMERR("hp_sw: unregister failed %d", r);
+}
+
+module_init(hp_sw_init);
+module_exit(hp_sw_exit);
+
+MODULE_DESCRIPTION("HP StorageWorks and FSC FibreCat (A/P) support for dm-multipath");
+MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>");
+MODULE_LICENSE("GPL");
Index: linux-2.6.22-rc1/drivers/md/Kconfig
===================================================================
--- linux-2.6.22-rc1.orig/drivers/md/Kconfig
+++ linux-2.6.22-rc1/drivers/md/Kconfig
@@ -271,6 +271,12 @@ config DM_DELAY
 
 	If unsure, say N.
 
+config DM_MULTIPATH_HP
+        tristate "HP MSA multipath support (EXPERIMENTAL)"
+        depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+        ---help---
+          Multipath support for HP MSA (Active/Passive) series hardware.
+
 endmenu
 
 endif

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

* Re: [2.6.22-rc1 PATCH] dm-hp-sw: HP Active/Passive hardware handler baseline
  2007-05-23 20:18 [2.6.22-rc1 PATCH] dm-hp-sw: HP Active/Passive hardware handler baseline Dave Wysochanski
@ 2007-05-23 21:17 ` Mike Christie
  2007-05-24  2:12   ` Dave Wysochanski
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Christie @ 2007-05-23 21:17 UTC (permalink / raw)
  To: device-mapper development

Dave Wysochanski wrote:
> +#include <scsi/scsi.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <scsi/scsi_dbg.h>
> +#include <scsi/scsi_device.h>
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_transport_fc.h>
> +#include <linux/list.h>
> +#include <linux/types.h>

you should do linux includes then scsi ones. Do you even need the fc,
host or cmnd includes?

> +
> +#include "dm.h"
> +#include "dm-hw-handler.h"
> +
> +#define DM_MSG_PREFIX "multipath hp"
> +
> +struct hp_sw_context {
> +	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
> +};
> +
> +
> +/**
> + * hp_sw_end_io - Completion handler for HP path activation.
> + * @req: failover request
> + * @error: scsi-ml error
> + *
> + *  Check sense data, free request structure, and notify dm that
> + *  pg initialization has completed.
> + *
> + * Context: scsi-ml softirq
> + *
> + * Possible optimizations
> + * 1. Actually check sense data for retryable error (e.g. NOT_READY)
> + */
> +static void hp_sw_end_io(struct request *req, int error)
> +{
> +	struct dm_path *path = req->end_io_data;
> +	unsigned err_flags;
> +
> +	if (!error) {
> +		err_flags = 0;
> +		DMDEBUG("hp_sw: path activation command on %s - success",
> +		       	path->dev->name);
> +	}
> +	else {

else should be on the same line as "{"


I also think we should handle the NOT_READY case that was reported before.


> +		DMWARN("hp_sw: path activation command on %s - error=0x%x",
> +		       path->dev->name, error);
> +		err_flags = MP_FAIL_PATH;
> +	}
> +
> +	req->end_io_data = NULL;
> +	__blk_put_request(req->q, req);
> +	dm_pg_init_complete(path, err_flags);
> +}
> +
> +/**
> + * hp_sw_get_request - Allocate an HP specific path activation request
> + * @path: path on which request will be sent (needed for request queue)
> + *
> + * The START command is used for path activation request.
> + * These arrays are controller-based failover, not LUN based.
> + * One START command issued to a single path will fail over all
> + * LUNs for the same controller.
> + *
> + * Possible optimizations
> + * 1. Make timeout configurable
> + * 2. Preallocate request
> + */
> +static struct request *hp_sw_get_request(struct dm_path *path)
> +{
> +	struct request *req=NULL;
> +	struct block_device *bdev = path->dev->bdev;
> +	struct request_queue *q = bdev_get_queue(bdev);
> +	struct hp_sw_context *h = path->hwhcontext;
> +
> +	req = blk_get_request(q, WRITE, GFP_ATOMIC);
> +	if (req == NULL)
> +		goto exit;
> +
> +	req->timeout = 60*HZ;
> +
> +	req->errors = 0;
> +	req->cmd_type = REQ_TYPE_BLOCK_PC;
> +	req->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
> +	req->end_io = hp_sw_end_io;
> +	req->end_io_data = path;
> +	req->sense = h->sense;
> +	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
> +
> +	memset(&req->cmd, 0, BLK_MAX_CDB);
> +	req->cmd[0] = START_STOP;
> +	req->cmd[4] = 1;
> +	req->cmd_len = COMMAND_SIZE(req->cmd[0]);
> +exit:
> +	return req;
> +}
> +
> +/**
> + * hp_sw_pg_init - HP path activation implementation.
> + * @hwh: hardware handler specific data
> + * @bypassed: unused; is the path group bypassed? (see dm-mpath.c)
> + * @path: path to send initialization command
> + *
> + * Send an HP-specific path activation command on 'path'.
> + * Do not try to optimize in any way, just send the activation command.
> + * More than one path activation command may be sent to the same controller.
> + * This seems to work fine for basic failover support.
> + *
> + * Possible optimizations
> + * 1. Detect an in-progress activation request and avoid submitting another one
> + * 2. Model the controller and only send a single activation request at a time
> + * 3. Determine the state of a path before sending an activation request
> + *
> + * Context: kmpathd (see process_queued_ios() in dm-mpath.c)
> + */
> +static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
> +			  struct dm_path *path)
> +{
> +	struct request *req;
> +	struct hp_sw_context *h;
> +	unsigned err_flags;
> +
> +	path->hwhcontext = hwh->context;
> +	h = (struct hp_sw_context *) hwh->context;
> +

you do not need the case do you?

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

* Re: [2.6.22-rc1 PATCH] dm-hp-sw: HP Active/Passive hardware handler baseline
  2007-05-23 21:17 ` Mike Christie
@ 2007-05-24  2:12   ` Dave Wysochanski
  0 siblings, 0 replies; 3+ messages in thread
From: Dave Wysochanski @ 2007-05-24  2:12 UTC (permalink / raw)
  To: device-mapper development

On Wed, 2007-05-23 at 16:17 -0500, Mike Christie wrote:
> Dave Wysochanski wrote:
> > +#include <scsi/scsi.h>
> > +#include <scsi/scsi_cmnd.h>
> > +#include <scsi/scsi_dbg.h>
> > +#include <scsi/scsi_device.h>
> > +#include <scsi/scsi_host.h>
> > +#include <scsi/scsi_transport_fc.h>
> > +#include <linux/list.h>
> > +#include <linux/types.h>
> 
> you should do linux includes then scsi ones. Do you even need the fc,
> host or cmnd includes?
> 
Indeed, some of them are unnecessary, thanks.
scsi_cmnd.h is necessary for SCSI_SENSE_BUFFERSIZE.  The only other one
I need is scsi/scsi.h (for START_STOP and COMMAND_SIZE).  Will rearrange
and fix.


> > +
> > +#include "dm.h"
> > +#include "dm-hw-handler.h"
> > +
> > +#define DM_MSG_PREFIX "multipath hp"
> > +
> > +struct hp_sw_context {
> > +	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
> > +};
> > +
> > +
> > +/**
> > + * hp_sw_end_io - Completion handler for HP path activation.
> > + * @req: failover request
> > + * @error: scsi-ml error
> > + *
> > + *  Check sense data, free request structure, and notify dm that
> > + *  pg initialization has completed.
> > + *
> > + * Context: scsi-ml softirq
> > + *
> > + * Possible optimizations
> > + * 1. Actually check sense data for retryable error (e.g. NOT_READY)
> > + */
> > +static void hp_sw_end_io(struct request *req, int error)
> > +{
> > +	struct dm_path *path = req->end_io_data;
> > +	unsigned err_flags;
> > +
> > +	if (!error) {
> > +		err_flags = 0;
> > +		DMDEBUG("hp_sw: path activation command on %s - success",
> > +		       	path->dev->name);
> > +	}
> > +	else {
> 
> else should be on the same line as "{"
> 

done.

> 
> I also think we should handle the NOT_READY case that was reported before.
> 

Will do.

> 
> > +		DMWARN("hp_sw: path activation command on %s - error=0x%x",
> > +		       path->dev->name, error);
> > +		err_flags = MP_FAIL_PATH;
> > +	}
> > +
> > +	req->end_io_data = NULL;
> > +	__blk_put_request(req->q, req);
> > +	dm_pg_init_complete(path, err_flags);
> > +}
> > +
> > +/**
> > + * hp_sw_get_request - Allocate an HP specific path activation request
> > + * @path: path on which request will be sent (needed for request queue)
> > + *
> > + * The START command is used for path activation request.
> > + * These arrays are controller-based failover, not LUN based.
> > + * One START command issued to a single path will fail over all
> > + * LUNs for the same controller.
> > + *
> > + * Possible optimizations
> > + * 1. Make timeout configurable
> > + * 2. Preallocate request
> > + */
> > +static struct request *hp_sw_get_request(struct dm_path *path)
> > +{
> > +	struct request *req=NULL;
> > +	struct block_device *bdev = path->dev->bdev;
> > +	struct request_queue *q = bdev_get_queue(bdev);
> > +	struct hp_sw_context *h = path->hwhcontext;
> > +
> > +	req = blk_get_request(q, WRITE, GFP_ATOMIC);
> > +	if (req == NULL)
> > +		goto exit;
> > +
> > +	req->timeout = 60*HZ;
> > +
> > +	req->errors = 0;
> > +	req->cmd_type = REQ_TYPE_BLOCK_PC;
> > +	req->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
> > +	req->end_io = hp_sw_end_io;
> > +	req->end_io_data = path;
> > +	req->sense = h->sense;
> > +	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
> > +
> > +	memset(&req->cmd, 0, BLK_MAX_CDB);
> > +	req->cmd[0] = START_STOP;
> > +	req->cmd[4] = 1;
> > +	req->cmd_len = COMMAND_SIZE(req->cmd[0]);
> > +exit:
> > +	return req;
> > +}
> > +
> > +/**
> > + * hp_sw_pg_init - HP path activation implementation.
> > + * @hwh: hardware handler specific data
> > + * @bypassed: unused; is the path group bypassed? (see dm-mpath.c)
> > + * @path: path to send initialization command
> > + *
> > + * Send an HP-specific path activation command on 'path'.
> > + * Do not try to optimize in any way, just send the activation command.
> > + * More than one path activation command may be sent to the same controller.
> > + * This seems to work fine for basic failover support.
> > + *
> > + * Possible optimizations
> > + * 1. Detect an in-progress activation request and avoid submitting another one
> > + * 2. Model the controller and only send a single activation request at a time
> > + * 3. Determine the state of a path before sending an activation request
> > + *
> > + * Context: kmpathd (see process_queued_ios() in dm-mpath.c)
> > + */
> > +static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
> > +			  struct dm_path *path)
> > +{
> > +	struct request *req;
> > +	struct hp_sw_context *h;
> > +	unsigned err_flags;
> > +
> > +	path->hwhcontext = hwh->context;
> > +	h = (struct hp_sw_context *) hwh->context;
> > +
> 
> you do not need the case do you?
> 

Do you mean "the context"?  I don't understand this comment.

Also, just looked and I probably do not need err_flags in hp_sw_pg_init.

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

end of thread, other threads:[~2007-05-24  2:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-23 20:18 [2.6.22-rc1 PATCH] dm-hp-sw: HP Active/Passive hardware handler baseline Dave Wysochanski
2007-05-23 21:17 ` Mike Christie
2007-05-24  2:12   ` Dave Wysochanski

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.