Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 314159 Details for
Bug 438761
LTC:5.4:201049:DM-MP SCSI Hardware Handlers
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
Changes in dm layer to use SCSI Hardware Handler
05-use_scsi_dh_in_multipath.patch (text/plain), 9.76 KB, created by
IBM Bug Proxy
on 2008-08-13 00:51:28 UTC
(
hide
)
Description:
Changes in dm layer to use SCSI Hardware Handler
Filename:
MIME Type:
Creator:
IBM Bug Proxy
Created:
2008-08-13 00:51:28 UTC
Size:
9.76 KB
patch
obsolete
>Subject: scsi_dh: Use SCSI device handler in dm-multipath > >From: Chandra Seetharaman <sekharan@us.ibm.com> > >This patch converts dm-mpath to use scsi device handlers instead of >dm's hardware handlers. > >This patch does not add any new functionality. Old behaviors remain and >userspace tools work as is except that arguments supplied with hardware >handler are ignored. > >One behavioral exception is: Activation of a path is synchronous in this >patch, opposed to the older behavior of being asynchronous (changed in >patch 07: scsi_dh: Add a single threaded workqueue for initializing a path) > >Note: There is no need to get a reference for the device handler module >(as it was done in the dm hardware handler case) here as the reference >is held when the device was first found. Instead we check and make sure >that support for the specified device is present at table load time. > >Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> >Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> >--- > drivers/md/Kconfig | 1 1 + 0 - 0 ! > drivers/md/dm-mpath.c | 226 111 + 115 - 0 ! > 2 files changed, 112 insertions(+), 115 deletions(-) > >Index: linux-2.6.18.ppc64/drivers/md/dm-mpath.c >=================================================================== >--- linux-2.6.18.ppc64.orig/drivers/md/dm-mpath.c >+++ linux-2.6.18.ppc64/drivers/md/dm-mpath.c >@@ -20,6 +20,7 @@ > #include <linux/slab.h> > #include <linux/time.h> > #include <linux/workqueue.h> >+#include <scsi/scsi_dh.h> > #include <asm/atomic.h> > > #define DM_MSG_PREFIX "multipath" >@@ -61,7 +62,7 @@ struct multipath { > > spinlock_t lock; > >- struct hw_handler hw_handler; >+ const char *hw_handler_name; > unsigned nr_priority_groups; > struct list_head priority_groups; > unsigned pg_init_required; /* pg_init needs calling? */ >@@ -109,6 +110,7 @@ static kmem_cache_t *_mpio_cache; > struct workqueue_struct *kmultipathd; > static void process_queued_ios(void *data); > static void trigger_event(void *data); >+static void pg_init_done(struct path *, int); > > > /*----------------------------------------------- >@@ -149,9 +151,12 @@ static struct priority_group *alloc_prio > static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) > { > struct pgpath *pgpath, *tmp; >+ struct multipath *m = (struct multipath *) ti->private; > > list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { > list_del(&pgpath->list); >+ if (m->hw_handler_name) >+ scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev)); > dm_put_device(ti, pgpath->path.dev); > free_pgpath(pgpath); > } >@@ -196,18 +201,13 @@ static struct multipath *alloc_multipath > static void free_multipath(struct multipath *m) > { > struct priority_group *pg, *tmp; >- struct hw_handler *hwh = &m->hw_handler; > > list_for_each_entry_safe(pg, tmp, &m->priority_groups, list) { > list_del(&pg->list); > free_priority_group(pg, m->ti); > } > >- if (hwh->type) { >- hwh->type->destroy(hwh); >- dm_put_hw_handler(hwh->type); >- } >- >+ kfree(m->hw_handler_name); > mempool_destroy(m->mpio_pool); > kfree(m); > } >@@ -219,12 +219,10 @@ static void free_multipath(struct multip > > static void __switch_pg(struct multipath *m, struct pgpath *pgpath) > { >- struct hw_handler *hwh = &m->hw_handler; >- > m->current_pg = pgpath->pg; > > /* Must we initialise the PG first, and queue I/O till it's ready? */ >- if (hwh->type && hwh->type->pg_init) { >+ if (m->hw_handler_name) { > m->pg_init_required = 1; > m->queue_io = 1; > } else { >@@ -404,7 +402,6 @@ static void dispatch_queued_ios(struct m > static void process_queued_ios(void *data) > { > struct multipath *m = (struct multipath *) data; >- struct hw_handler *hwh = &m->hw_handler; > struct pgpath *pgpath = NULL; > unsigned init_required = 0, must_queue = 1; > unsigned long flags; >@@ -433,8 +430,11 @@ static void process_queued_ios(void *dat > out: > spin_unlock_irqrestore(&m->lock, flags); > >- if (init_required) >- hwh->type->pg_init(hwh, pgpath->pg->bypassed, &pgpath->path); >+ if (init_required) { >+ struct path *path = &pgpath->path; >+ int ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev)); >+ pg_init_done(path, ret); >+ } > > if (!must_queue) > dispatch_queued_ios(m); >@@ -545,6 +545,7 @@ static struct pgpath *parse_path(struct > { > int r; > struct pgpath *p; >+ struct multipath *m = (struct multipath *) ti->private; > > /* we need at least a path arg */ > if (as->argc < 1) { >@@ -563,6 +564,15 @@ static struct pgpath *parse_path(struct > goto bad; > } > >+ if (m->hw_handler_name) { >+ r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev), >+ m->hw_handler_name); >+ if (r < 0) { >+ dm_put_device(ti, p->path.dev); >+ goto bad; >+ } >+ } >+ > r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error); > if (r) { > dm_put_device(ti, p->path.dev); >@@ -647,35 +657,27 @@ static struct priority_group *parse_prio > static int parse_hw_handler(struct arg_set *as, struct multipath *m, > struct dm_target *ti) > { >- int r; >- struct hw_handler_type *hwht; > unsigned hw_argc; > > static struct param _params[] = { > {0, 1024, "invalid number of hardware handler args"}, > }; > >- r = read_param(_params, shift(as), &hw_argc, &ti->error); >- if (r) >+ if (read_param(_params, shift(as), &hw_argc, &ti->error)) > return -EINVAL; > > if (!hw_argc) > return 0; > >- hwht = dm_get_hw_handler(shift(as)); >- if (!hwht) { >+ m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL); >+ request_module("scsi_dh_%s", m->hw_handler_name); >+ if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { > ti->error = "unknown hardware handler type"; >+ kfree(m->hw_handler_name); >+ m->hw_handler_name = NULL; > return -EINVAL; > } > >- r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv); >- if (r) { >- dm_put_hw_handler(hwht); >- ti->error = "hardware handler constructor failed"; >- return r; >- } >- >- m->hw_handler.type = hwht; > consume(as, hw_argc - 1); > > return 0; >@@ -749,6 +751,7 @@ static int multipath_ctr(struct dm_targe > } > > m->ti = ti; >+ ti->private = m; > > r = parse_features(&as, m, ti); > if (r) >@@ -790,8 +793,6 @@ static int multipath_ctr(struct dm_targe > goto bad; > } > >- ti->private = m; >- > return 0; > > bad: >@@ -1061,14 +1062,74 @@ void dm_pg_init_complete(struct path *pa > spin_unlock_irqrestore(&m->lock, flags); > } > >+static void pg_init_done(struct path *path, int errors) >+{ >+ struct pgpath *pgpath = path_to_pgpath(path); >+ struct priority_group *pg = pgpath->pg; >+ struct multipath *m = pg->m; >+ unsigned long flags; >+ >+ /* device or driver problems */ >+ switch (errors) { >+ case SCSI_DH_OK: >+ break; >+ case SCSI_DH_NOSYS: >+ if (!m->hw_handler_name) { >+ errors = 0; >+ break; >+ } >+ DMERR("Cannot failover device because scsi_dh_%s was not " >+ "loaded.", m->hw_handler_name); >+ /* >+ * Fail path for now, so we do not ping pong >+ */ >+ fail_path(pgpath); >+ break; >+ case SCSI_DH_DEV_TEMP_BUSY: >+ /* >+ * Probably doing something like FW upgrade on the >+ * controller so try the other pg. >+ */ >+ bypass_pg(m, pg, 1); >+ break; >+ /* TODO: For SCSI_DH_RETRY we should wait a couple seconds */ >+ case SCSI_DH_RETRY: >+ case SCSI_DH_IMM_RETRY: >+ case SCSI_DH_RES_TEMP_UNAVAIL: >+ if (pg_init_limit_reached(m, pgpath)) >+ fail_path(pgpath); >+ errors = 0; >+ break; >+ default: >+ /* >+ * We probably do not want to fail the path for a device >+ * error, but this is what the old dm did. In future >+ * patches we can do more advanced handling. >+ */ >+ fail_path(pgpath); >+ } >+ >+ spin_lock_irqsave(&m->lock, flags); >+ if (errors) { >+ DMERR("Could not failover device. Error %d.", errors); >+ m->current_pgpath = NULL; >+ m->current_pg = NULL; >+ } else if (!m->pg_init_required) { >+ m->queue_io = 0; >+ pg->bypassed = 0; >+ } >+ >+ m->pg_init_in_progress = 0; >+ queue_work(kmultipathd, &m->process_queued_ios); >+ spin_unlock_irqrestore(&m->lock, flags); >+} >+ > /* > * end_io handling > */ > static int do_end_io(struct multipath *m, struct bio *bio, > int error, struct mpath_io *mpio) > { >- struct hw_handler *hwh = &m->hw_handler; >- unsigned err_flags = MP_FAIL_PATH; /* Default behavior */ > unsigned long flags; > > if (!error) >@@ -1095,19 +1156,8 @@ static int do_end_io(struct multipath *m > } > spin_unlock_irqrestore(&m->lock, flags); > >- if (hwh->type && hwh->type->error) >- err_flags = hwh->type->error(hwh, bio); >- >- if (mpio->pgpath) { >- if (err_flags & MP_FAIL_PATH) >- fail_path(mpio->pgpath); >- >- if (err_flags & MP_BYPASS_PG) >- bypass_pg(m, mpio->pgpath->pg, 1); >- } >- >- if (err_flags & MP_ERROR_IO) >- return -EIO; >+ if (mpio->pgpath) >+ fail_path(mpio->pgpath); > > requeue: > dm_bio_restore(&mpio->details, bio); >@@ -1192,7 +1242,6 @@ static int multipath_status(struct dm_ta > int sz = 0; > unsigned long flags; > struct multipath *m = (struct multipath *) ti->private; >- struct hw_handler *hwh = &m->hw_handler; > struct priority_group *pg; > struct pgpath *p; > unsigned pg_num; >@@ -1212,12 +1261,10 @@ static int multipath_status(struct dm_ta > DMEMIT("pg_init_retries %u ", m->pg_init_retries); > } > >- if (hwh->type && hwh->type->status) >- sz += hwh->type->status(hwh, type, result + sz, maxlen - sz); >- else if (!hwh->type || type == STATUSTYPE_INFO) >+ if (!m->hw_handler_name || type == STATUSTYPE_INFO) > DMEMIT("0 "); > else >- DMEMIT("1 %s ", hwh->type->name); >+ DMEMIT("1 %s ", m->hw_handler_name); > > DMEMIT("%u ", m->nr_priority_groups); > >Index: linux-2.6.18.ppc64/drivers/md/Kconfig >=================================================================== >--- linux-2.6.18.ppc64.orig/drivers/md/Kconfig >+++ linux-2.6.18.ppc64/drivers/md/Kconfig >@@ -240,6 +240,11 @@ config DM_ZERO > config DM_MULTIPATH > tristate "Multipath target (EXPERIMENTAL)" > depends on BLK_DEV_DM && EXPERIMENTAL >+ # nasty syntax but means make DM_MULTIPATH independent >+ # of SCSI_DH if the latter isn't defined but if >+ # it is, DM_MULTIPATH must depend on it. We get a build >+ # error if SCSI_DH=m and DM_MULTIPATH=y otherwise. >+ depends on SCSI_DH || !SCSI_DH > ---help--- > Allow volume managers to support multipath hardware. >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 438761
:
314153
|
314154
|
314155
|
314156
|
314157
|
314158
| 314159 |
314160
|
314161
|
314162
|
314163
|
314339
|
314426
|
314828
|
314829
|
316641