Outline EMC hw_handler. --- diff/drivers/md/Kconfig 2004-10-29 15:37:28.000000000 +0100 +++ source/drivers/md/Kconfig 2004-10-29 15:40:09.000000000 +0100 @@ -224,5 +224,11 @@ ---help--- Allow volume managers to support multipath hardware. +config DM_MULTIPATH_EMC + tristate "EMC multipath support (EXPERIMENTAL)" + depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL + ---help--- + Multipath support for EMC hardware. + endmenu --- diff/drivers/md/Makefile 2004-10-29 15:37:46.000000000 +0100 +++ source/drivers/md/Makefile 2004-10-29 15:40:09.000000000 +0100 @@ -29,6 +29,7 @@ obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o +obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_MIRROR) += dm-mirror.o obj-$(CONFIG_DM_ZERO) += dm-zero.o --- diff/drivers/md/dm-emc.c 1970-01-01 01:00:00.000000000 +0100 +++ source/drivers/md/dm-emc.c 2004-10-29 15:40:09.000000000 +0100 @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2004 SUSE LINUX AG. All rights reserved. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * + * This file is released under the GPL. + * + * Multipath support for EMC CLARiiON AX/CX-series hardware. + */ + +#include "dm.h" +#include "dm-hw-handler.h" + +struct emc_handler { + spinlock_t lock; + + /* FIXME Add state variables */ + unsigned short_trespass; +}; + +static struct emc_handler *alloc_emc_handler(void) +{ + struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL); + + if (h) { + h->lock = SPIN_LOCK_UNLOCKED; + } + + return h; +} + +static int emc_ctr(struct hw_handler *hwh, unsigned argc, char **argv) +{ + struct emc_handler *h; + + h = alloc_emc_handler(); + if (!h) + return -ENOMEM; + + /* FIXME: Parse [0|1] parameter to send short trespass command for + * FC series */ + + hwh->context = h; + return 0; +} + +static void emc_dtr(struct hw_handler *hwh) +{ + struct emc_handler *h = (struct emc_handler *) hwh->context; + + kfree(h); + hwh->context = NULL; +} + +static unsigned emc_err(struct hw_handler *hwh, struct bio *bio) +{ + int sense; + + /* FIXME: Patch from axboe still missing */ +#if 0 + if (bio->bi_error & BIO_SENSE) { + sense = bio->bi_error & 0xffffff; /* sense key / asc / ascq */ + + if (sense == 0x020403) { + /* LUN Not Ready - Manual Intervention Required + * indicates this is a passive path. + * + * FIXME: However, if this is seen and EVPD C0 + * indicates that this is due to a NDU in + * progress, we should set FAIL_PATH too. + * This indicates we might have to do a SCSI + * inquiry in the end_io path. Ugh. */ + return MP_BYPASS_PG | MP_RETRY_IO; + } else if (sense == 0x052501) { + /* An array based copy is in progress. Do not + * fail the path, do not bypass to another PG, + * do not retry. Fail the IO immediately. + * (Actually this is the same conclusion as in + * the default handler, but lets make sure.) */ + return 0; + } else if (sense == 0x062900) { + /* Unit Attention Code. This is the first IO + * to the new path, so just retry. */ + return MP_RETRY_IO; + } + } +#endif + + /* Try default handler */ + return dm_scsi_err_handler(hwh, bio); +} + +static struct hw_handler_type emc_hwh = { + .name = "emc", + .module = THIS_MODULE, + .ctr = emc_ctr, + .dtr = emc_dtr, + .err = emc_err, +}; + +static int __init dm_emc_init(void) +{ + int r = dm_register_hw_handler(&emc_hwh); + + if (r < 0) + DMERR("emc: register failed %d", r); + + DMINFO("dm-emc version 0.0.1 loaded"); + + return r; +} + +static void __exit dm_emc_exit(void) +{ + int r = dm_unregister_hw_handler(&emc_hwh); + + if (r < 0) + DMERR("emc: unregister failed %d", r); +} + +module_init(dm_emc_init); +module_exit(dm_emc_exit); + +MODULE_DESCRIPTION(DM_NAME " EMC CX/AX/FC-family multipath"); +MODULE_AUTHOR("Lars Marowsky-Bree "); +MODULE_LICENSE("GPL");