FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Device-mapper Development

 
 
LinkBack Thread Tools
 
Old 05-23-2008, 02:08 AM
Chandra Seetharaman
 
Default scsi_dh: attach to hardware handler from dm-mpath

Looks good to me.

On Tue, 2008-05-20 at 16:05 +0200, Hannes Reinecke wrote:
> multipath keeps a separate device table which may be
> more current than the built-in one.
> So we should make sure to always call ->attach whenever
> a multipath map with hardware handler is instantiated.
> And we should call ->detach on removal, too.
>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
> drivers/md/dm-mpath.c | 13 ++++++
> drivers/scsi/device_handler/scsi_dh.c | 74 +++++++++++++++++++++++++++++++++
> include/scsi/scsi_dh.h | 2 +
> 3 files changed, 89 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
> index e8f704a..bd2bcf4 100644
> --- a/drivers/md/dm-mpath.c
> +++ b/drivers/md/dm-mpath.c
> @@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void)
> 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);
> }
> @@ -546,6 +549,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
> {
> int r;
> struct pgpath *p;
> + struct multipath *m = (struct multipath *) ti->private;
>
> /* we need at least a path arg */
> if (as->argc < 1) {
> @@ -564,6 +568,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
> 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);
> diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
> index b80fae7..a9404b5 100644
> --- a/drivers/scsi/device_handler/scsi_dh.c
> +++ b/drivers/scsi/device_handler/scsi_dh.c
> @@ -362,6 +362,80 @@ int scsi_dh_handler_exist(const char *name)
> }
> EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
>
> +/*
> + * scsi_dh_handler_attach - Attach device handler
> + * @sdev - sdev the handler should be attached to
> + * @name - name of the handler to attach
> + */
> +int scsi_dh_attach(struct request_queue *q, const char *name)
> +{
> + unsigned long flags;
> + struct scsi_device *sdev;
> + struct scsi_device_handler *scsi_dh;
> + int err = 0;
> +
> + scsi_dh = get_device_handler(name);
> + if (!scsi_dh)
> + return -EINVAL;
> +
> + spin_lock_irqsave(q->queue_lock, flags);
> + sdev = q->queuedata;
> + if (!sdev || !get_device(&sdev->sdev_gendev))
> + err = -ENODEV;
> + spin_unlock_irqrestore(q->queue_lock, flags);
> +
> + if (!err) {
> + err = scsi_dh_handler_attach(sdev, scsi_dh);
> +
> + put_device(&sdev->sdev_gendev);
> + }
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(scsi_dh_attach);
> +
> +/*
> + * scsi_dh_handler_detach - Detach device handler
> + * @sdev - sdev the handler should be detached from
> + *
> + * This function will detach the device handler only
> + * if the sdev is not part of the internal list, ie
> + * if it has been attached manually.
> + */
> +void scsi_dh_detach(struct request_queue *q)
> +{
> + unsigned long flags;
> + struct scsi_device *sdev;
> + struct scsi_device_handler *scsi_dh = NULL;
> + int i, found = 0;
> +
> + spin_lock_irqsave(q->queue_lock, flags);
> + sdev = q->queuedata;
> + if (!sdev || !get_device(&sdev->sdev_gendev))
> + sdev = NULL;
> + spin_unlock_irqrestore(q->queue_lock, flags);
> +
> + if (!sdev)
> + return;
> +
> + if (sdev->scsi_dh_data) {
> + scsi_dh = sdev->scsi_dh_data->scsi_dh;
> + for(i = 0; scsi_dh->devlist[i].vendor; i++) {
> + if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
> + strlen(scsi_dh->devlist[i].vendor)) &&
> + !strncmp(sdev->model, scsi_dh->devlist[i].model,
> + strlen(scsi_dh->devlist[i].model))) {
> + found = 1;
> + break;
> + }
> + }
> + /* sdev not on internal list, detach */
> + if (!found)
> + scsi_dh_handler_detach(sdev);
> + }
> + put_device(&sdev->sdev_gendev);
> +}
> +EXPORT_SYMBOL_GPL(scsi_dh_detach);
> +
> static struct notifier_block scsi_dh_nb = {
> .notifier_call = scsi_dh_notifier
> };
> diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
> index 5d05ac0..8032e51 100644
> --- a/include/scsi/scsi_dh.h
> +++ b/include/scsi/scsi_dh.h
> @@ -59,3 +59,5 @@ enum {
>
> extern int scsi_dh_activate(struct request_queue *);
> extern int scsi_dh_handler_exist(const char *);
> +extern int scsi_dh_attach(struct request_queue *, const char *);
> +extern void scsi_dh_detach(struct request_queue *q);

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 05-23-2008, 11:40 AM
Hannes Reinecke
 
Default scsi_dh: attach to hardware handler from dm-mpath

On Thu, May 22, 2008 at 09:14:54AM +0100, James Bottomley wrote:
> On Wed, 2008-05-21 at 08:18 +0200, Hannes Reinecke wrote:
[ .. ]
> > Why? You can detach with dh_state, too; just do an
> >
> > echo detach > /sys/block/sdX/device/dh_state
> >
> > and the hardware handler will detach.
> > So no additional attribute is required.
>
> Actually, if you're going down this route, it makes more sense to have
> the device handler be a driver ... remember you were the one promising
> multiple driver binding at the FS/Storage summit ... that way we can
> use all the generic driver standard interfaces for manual
> binding/unbinding. Plus we can place the attributes as driver attribute
> groups.
>
Hmm. Actually this very discussion I had with Kay Sievers earlier this
week when we tried to make bsg useable for udev.
The problem here is that we really want the device_handler to kick in
_before_ any of the 'normal' SCSI ULD starts it's probing, as we might
want to suppress I/O on this channel.

If we were to use the normal driver binding for this we'd be called
at the same level with the normal ULDs, making it unpredictable at which
time we're called.

And it was actually Greg KH which promised the multiple driver binding,
but seems that he's not getting around doing this anytime soon.
Hmm; maybe I can convince Kay on doing it ...
But want we really want to do is _not_ having these 'special' handlers
called at any time during bus probing, but having a fixed order like:

sdev probing
- (optional) device handler attach
- bsg attach
- SCSI ULD probing

We would like to have bsg available before ULD probing, as then we could
use the bsg device nodes in general in udev (like calling scsi_id on it).
It _might_ be possible to handle these cases with multiple driver binding,
but seeing that there's no-one currently working on it I'd like to stick
with the current approach.

Cheers,

Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 N�g
GF: Markus Rex, HRB 16746 (AG N�g)

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 05-23-2008, 02:06 PM
James Bottomley
 
Default scsi_dh: attach to hardware handler from dm-mpath

On Fri, 2008-05-23 at 13:40 +0200, Hannes Reinecke wrote:
> On Thu, May 22, 2008 at 09:14:54AM +0100, James Bottomley wrote:
> > On Wed, 2008-05-21 at 08:18 +0200, Hannes Reinecke wrote:
> [ .. ]
> > > Why? You can detach with dh_state, too; just do an
> > >
> > > echo detach > /sys/block/sdX/device/dh_state
> > >
> > > and the hardware handler will detach.
> > > So no additional attribute is required.
> >
> > Actually, if you're going down this route, it makes more sense to have
> > the device handler be a driver ... remember you were the one promising
> > multiple driver binding at the FS/Storage summit ... that way we can
> > use all the generic driver standard interfaces for manual
> > binding/unbinding. Plus we can place the attributes as driver attribute
> > groups.
> >
> Hmm. Actually this very discussion I had with Kay Sievers earlier this
> week when we tried to make bsg useable for udev.
> The problem here is that we really want the device_handler to kick in
> _before_ any of the 'normal' SCSI ULD starts it's probing, as we might
> want to suppress I/O on this channel.

That's easily doable provided there's some type of trigger for
registration. At the moment, it's just a binding free for all since
drivers bind either when they appear (for existing devices) or when the
device appears (for existing drivers). For the new multiple driver
binding code, I could see a good case for either strictly controlling
the ordering (for binding a new device to existing drivers) or even
making the bindings classification driven.

> If we were to use the normal driver binding for this we'd be called
> at the same level with the normal ULDs, making it unpredictable at which
> time we're called.

Depends how it's done. Right at the moment with only a single driver
there's no concept of ordering ... if it's list based, then it would be
in list order, but there's no reason the order can't be dictated by the
bus.

> And it was actually Greg KH which promised the multiple driver binding,
> but seems that he's not getting around doing this anytime soon.

Well, since we have the use case, the rules of open source would tend to
dictate that we have the impetus to do it. Particularly when there's
tricky questions like binding order to be answered.

> Hmm; maybe I can convince Kay on doing it ...
> But want we really want to do is _not_ having these 'special' handlers
> called at any time during bus probing, but having a fixed order like:
>
> sdev probing
> - (optional) device handler attach
> - bsg attach
> - SCSI ULD probing
>
> We would like to have bsg available before ULD probing, as then we could
> use the bsg device nodes in general in udev (like calling scsi_id on it).
> It _might_ be possible to handle these cases with multiple driver binding,
> but seeing that there's no-one currently working on it I'd like to stick
> with the current approach.

I think a simple priority based scheme would cope with that. Say a
single integer in the bus for max priority and then it loops from zero
to max binding all drivers equal to that priority. We could use 3 (zero
for device handler, one for bsg and 2 for ULD). We should probably use
1 as the default for everything, giving the ability to bind either
before or after the default (using zero or 2).

James


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 06-24-2008, 10:05 AM
 
Default scsi_dh: attach to hardware handler from dm-mpath

multipath keeps a separate device table which may be
more current than the built-in one.
So we should make sure to always call ->attach whenever
a multipath map with hardware handler is instantiated.
And we should call ->detach on removal, too.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/md/dm-mpath.c | 13 ++++++
drivers/scsi/device_handler/scsi_dh.c | 68 ++++++++++++++++++++++++++++++++-
include/scsi/scsi_dh.h | 2 +
3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index e8f704a..bd2bcf4 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void)
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);
}
@@ -546,6 +549,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
{
int r;
struct pgpath *p;
+ struct multipath *m = (struct multipath *) ti->private;

/* we need at least a path arg */
if (as->argc < 1) {
@@ -564,6 +568,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
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);
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index 7cbd1f6..a505e83 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -95,8 +95,8 @@ static void scsi_dh_handler_detach(struct scsi_device *sdev,
if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh)
return;

- if (scsi_dh->detach)
- scsi_dh->detach(sdev);
+ if (sdev->scsi_dh_data->scsi_dh->detach)
+ sdev->scsi_dh_data->scsi_dh->detach(sdev);
}

/*
@@ -366,6 +366,70 @@ int scsi_dh_handler_exist(const char *name)
}
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);

+/*
+ * scsi_dh_handler_attach - Attach device handler
+ * @sdev - sdev the handler should be attached to
+ * @name - name of the handler to attach
+ */
+int scsi_dh_attach(struct request_queue *q, const char *name)
+{
+ unsigned long flags;
+ struct scsi_device *sdev;
+ struct scsi_device_handler *scsi_dh;
+ int err = 0;
+
+ scsi_dh = get_device_handler(name);
+ if (!scsi_dh)
+ return -EINVAL;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ sdev = q->queuedata;
+ if (!sdev || !get_device(&sdev->sdev_gendev))
+ err = -ENODEV;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!err) {
+ err = scsi_dh_handler_attach(sdev, scsi_dh);
+
+ put_device(&sdev->sdev_gendev);
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(scsi_dh_attach);
+
+/*
+ * scsi_dh_handler_detach - Detach device handler
+ * @sdev - sdev the handler should be detached from
+ *
+ * This function will detach the device handler only
+ * if the sdev is not part of the internal list, ie
+ * if it has been attached manually.
+ */
+void scsi_dh_detach(struct request_queue *q)
+{
+ unsigned long flags;
+ struct scsi_device *sdev;
+ struct scsi_device_handler *scsi_dh = NULL;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ sdev = q->queuedata;
+ if (!sdev || !get_device(&sdev->sdev_gendev))
+ sdev = NULL;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!sdev)
+ return;
+
+ if (sdev->scsi_dh_data) {
+ /* if sdev is not on internal list, detach */
+ scsi_dh = sdev->scsi_dh_data->scsi_dh;
+ if (!device_handler_match(scsi_dh, sdev))
+ scsi_dh_handler_detach(sdev, scsi_dh);
+ }
+ put_device(&sdev->sdev_gendev);
+}
+EXPORT_SYMBOL_GPL(scsi_dh_detach);
+
static struct notifier_block scsi_dh_nb = {
.notifier_call = scsi_dh_notifier
};
diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
index 5d05ac0..8032e51 100644
--- a/include/scsi/scsi_dh.h
+++ b/include/scsi/scsi_dh.h
@@ -59,3 +59,5 @@ enum {

extern int scsi_dh_activate(struct request_queue *);
extern int scsi_dh_handler_exist(const char *);
+extern int scsi_dh_attach(struct request_queue *, const char *);
+extern void scsi_dh_detach(struct request_queue *q);
--
1.5.2.4

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 06-26-2008, 01:00 AM
Chandra Seetharaman
 
Default scsi_dh: attach to hardware handler from dm-mpath

Acked-by: Chandra Seetharaman <sekharan@us.ibm.com>

On Tue, 2008-06-24 at 12:05 +0200, Hannes Reinecke wrote:
> multipath keeps a separate device table which may be
> more current than the built-in one.
> So we should make sure to always call ->attach whenever
> a multipath map with hardware handler is instantiated.
> And we should call ->detach on removal, too.
>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
> drivers/md/dm-mpath.c | 13 ++++++
> drivers/scsi/device_handler/scsi_dh.c | 68 ++++++++++++++++++++++++++++++++-
> include/scsi/scsi_dh.h | 2 +
> 3 files changed, 81 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
> index e8f704a..bd2bcf4 100644
> --- a/drivers/md/dm-mpath.c
> +++ b/drivers/md/dm-mpath.c
> @@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void)
> 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);
> }
> @@ -546,6 +549,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
> {
> int r;
> struct pgpath *p;
> + struct multipath *m = (struct multipath *) ti->private;
>
> /* we need at least a path arg */
> if (as->argc < 1) {
> @@ -564,6 +568,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
> 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);
> diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
> index 7cbd1f6..a505e83 100644
> --- a/drivers/scsi/device_handler/scsi_dh.c
> +++ b/drivers/scsi/device_handler/scsi_dh.c
> @@ -95,8 +95,8 @@ static void scsi_dh_handler_detach(struct scsi_device *sdev,
> if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh)
> return;
>
> - if (scsi_dh->detach)
> - scsi_dh->detach(sdev);
> + if (sdev->scsi_dh_data->scsi_dh->detach)
> + sdev->scsi_dh_data->scsi_dh->detach(sdev);
> }
>
> /*
> @@ -366,6 +366,70 @@ int scsi_dh_handler_exist(const char *name)
> }
> EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
>
> +/*
> + * scsi_dh_handler_attach - Attach device handler
> + * @sdev - sdev the handler should be attached to
> + * @name - name of the handler to attach
> + */
> +int scsi_dh_attach(struct request_queue *q, const char *name)
> +{
> + unsigned long flags;
> + struct scsi_device *sdev;
> + struct scsi_device_handler *scsi_dh;
> + int err = 0;
> +
> + scsi_dh = get_device_handler(name);
> + if (!scsi_dh)
> + return -EINVAL;
> +
> + spin_lock_irqsave(q->queue_lock, flags);
> + sdev = q->queuedata;
> + if (!sdev || !get_device(&sdev->sdev_gendev))
> + err = -ENODEV;
> + spin_unlock_irqrestore(q->queue_lock, flags);
> +
> + if (!err) {
> + err = scsi_dh_handler_attach(sdev, scsi_dh);
> +
> + put_device(&sdev->sdev_gendev);
> + }
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(scsi_dh_attach);
> +
> +/*
> + * scsi_dh_handler_detach - Detach device handler
> + * @sdev - sdev the handler should be detached from
> + *
> + * This function will detach the device handler only
> + * if the sdev is not part of the internal list, ie
> + * if it has been attached manually.
> + */
> +void scsi_dh_detach(struct request_queue *q)
> +{
> + unsigned long flags;
> + struct scsi_device *sdev;
> + struct scsi_device_handler *scsi_dh = NULL;
> +
> + spin_lock_irqsave(q->queue_lock, flags);
> + sdev = q->queuedata;
> + if (!sdev || !get_device(&sdev->sdev_gendev))
> + sdev = NULL;
> + spin_unlock_irqrestore(q->queue_lock, flags);
> +
> + if (!sdev)
> + return;
> +
> + if (sdev->scsi_dh_data) {
> + /* if sdev is not on internal list, detach */
> + scsi_dh = sdev->scsi_dh_data->scsi_dh;
> + if (!device_handler_match(scsi_dh, sdev))
> + scsi_dh_handler_detach(sdev, scsi_dh);
> + }
> + put_device(&sdev->sdev_gendev);
> +}
> +EXPORT_SYMBOL_GPL(scsi_dh_detach);
> +
> static struct notifier_block scsi_dh_nb = {
> .notifier_call = scsi_dh_notifier
> };
> diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
> index 5d05ac0..8032e51 100644
> --- a/include/scsi/scsi_dh.h
> +++ b/include/scsi/scsi_dh.h
> @@ -59,3 +59,5 @@ enum {
>
> extern int scsi_dh_activate(struct request_queue *);
> extern int scsi_dh_handler_exist(const char *);
> +extern int scsi_dh_attach(struct request_queue *, const char *);
> +extern void scsi_dh_detach(struct request_queue *q);

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 07-17-2008, 07:39 AM
 
Default scsi_dh: attach to hardware handler from dm-mpath

multipath keeps a separate device table which may be
more current than the built-in one.
So we should make sure to always call ->attach whenever
a multipath map with hardware handler is instantiated.
And we should call ->detach on removal, too.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/md/dm-mpath.c | 13 +++++++
drivers/scsi/device_handler/scsi_dh.c | 64 +++++++++++++++++++++++++++++++++
include/scsi/scsi_dh.h | 2 +
3 files changed, 79 insertions(+), 0 deletions(-)

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index e8f704a..bd2bcf4 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void)
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);
}
@@ -546,6 +549,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
{
int r;
struct pgpath *p;
+ struct multipath *m = (struct multipath *) ti->private;

/* we need at least a path arg */
if (as->argc < 1) {
@@ -564,6 +568,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
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);
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index e90df9d..a915968 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -369,6 +369,70 @@ int scsi_dh_handler_exist(const char *name)
}
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);

+/*
+ * scsi_dh_handler_attach - Attach device handler
+ * @sdev - sdev the handler should be attached to
+ * @name - name of the handler to attach
+ */
+int scsi_dh_attach(struct request_queue *q, const char *name)
+{
+ unsigned long flags;
+ struct scsi_device *sdev;
+ struct scsi_device_handler *scsi_dh;
+ int err = 0;
+
+ scsi_dh = get_device_handler(name);
+ if (!scsi_dh)
+ return -EINVAL;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ sdev = q->queuedata;
+ if (!sdev || !get_device(&sdev->sdev_gendev))
+ err = -ENODEV;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!err) {
+ err = scsi_dh_handler_attach(sdev, scsi_dh);
+
+ put_device(&sdev->sdev_gendev);
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(scsi_dh_attach);
+
+/*
+ * scsi_dh_handler_detach - Detach device handler
+ * @sdev - sdev the handler should be detached from
+ *
+ * This function will detach the device handler only
+ * if the sdev is not part of the internal list, ie
+ * if it has been attached manually.
+ */
+void scsi_dh_detach(struct request_queue *q)
+{
+ unsigned long flags;
+ struct scsi_device *sdev;
+ struct scsi_device_handler *scsi_dh = NULL;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ sdev = q->queuedata;
+ if (!sdev || !get_device(&sdev->sdev_gendev))
+ sdev = NULL;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!sdev)
+ return;
+
+ if (sdev->scsi_dh_data) {
+ /* if sdev is not on internal list, detach */
+ scsi_dh = sdev->scsi_dh_data->scsi_dh;
+ if (!device_handler_match(scsi_dh, sdev))
+ scsi_dh_handler_detach(sdev, scsi_dh);
+ }
+ put_device(&sdev->sdev_gendev);
+}
+EXPORT_SYMBOL_GPL(scsi_dh_detach);
+
static struct notifier_block scsi_dh_nb = {
.notifier_call = scsi_dh_notifier
};
diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
index 3b486d9..78ba73f 100644
--- a/include/scsi/scsi_dh.h
+++ b/include/scsi/scsi_dh.h
@@ -58,3 +58,5 @@ enum {

extern int scsi_dh_activate(struct request_queue *);
extern int scsi_dh_handler_exist(const char *);
+extern int scsi_dh_attach(struct request_queue *, const char *);
+extern void scsi_dh_detach(struct request_queue *q);
--
1.5.2.4

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 07-17-2008, 11:53 PM
Chandra Seetharaman
 
Default scsi_dh: attach to hardware handler from dm-mpath

multipath keeps a separate device table which may be
more current than the built-in one.
So we should make sure to always call ->attach whenever
a multipath map with hardware handler is instantiated.
And we should call ->detach on removal, too.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
drivers/md/dm-mpath.c | 13 +++++++
drivers/scsi/device_handler/scsi_dh.c | 64 +++++++++++++++++++++++++++++++++
include/scsi/scsi_dh.h | 2 +
3 files changed, 79 insertions(+), 0 deletions(-)

Index: linux-2.6.26-git5/drivers/md/dm-mpath.c
================================================== =================
--- linux-2.6.26-git5.orig/drivers/md/dm-mpath.c
+++ linux-2.6.26-git5/drivers/md/dm-mpath.c
@@ -147,9 +147,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);
}
@@ -546,6 +549,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) {
@@ -564,6 +568,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);
Index: linux-2.6.26-git5/drivers/scsi/device_handler/scsi_dh.c
================================================== =================
--- linux-2.6.26-git5.orig/drivers/scsi/device_handler/scsi_dh.c
+++ linux-2.6.26-git5/drivers/scsi/device_handler/scsi_dh.c
@@ -369,6 +369,70 @@ int scsi_dh_handler_exist(const char *na
}
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);

+/*
+ * scsi_dh_handler_attach - Attach device handler
+ * @sdev - sdev the handler should be attached to
+ * @name - name of the handler to attach
+ */
+int scsi_dh_attach(struct request_queue *q, const char *name)
+{
+ unsigned long flags;
+ struct scsi_device *sdev;
+ struct scsi_device_handler *scsi_dh;
+ int err = 0;
+
+ scsi_dh = get_device_handler(name);
+ if (!scsi_dh)
+ return -EINVAL;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ sdev = q->queuedata;
+ if (!sdev || !get_device(&sdev->sdev_gendev))
+ err = -ENODEV;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!err) {
+ err = scsi_dh_handler_attach(sdev, scsi_dh);
+
+ put_device(&sdev->sdev_gendev);
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(scsi_dh_attach);
+
+/*
+ * scsi_dh_handler_detach - Detach device handler
+ * @sdev - sdev the handler should be detached from
+ *
+ * This function will detach the device handler only
+ * if the sdev is not part of the internal list, ie
+ * if it has been attached manually.
+ */
+void scsi_dh_detach(struct request_queue *q)
+{
+ unsigned long flags;
+ struct scsi_device *sdev;
+ struct scsi_device_handler *scsi_dh = NULL;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ sdev = q->queuedata;
+ if (!sdev || !get_device(&sdev->sdev_gendev))
+ sdev = NULL;
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!sdev)
+ return;
+
+ if (sdev->scsi_dh_data) {
+ /* if sdev is not on internal list, detach */
+ scsi_dh = sdev->scsi_dh_data->scsi_dh;
+ if (!device_handler_match(scsi_dh, sdev))
+ scsi_dh_handler_detach(sdev, scsi_dh);
+ }
+ put_device(&sdev->sdev_gendev);
+}
+EXPORT_SYMBOL_GPL(scsi_dh_detach);
+
static struct notifier_block scsi_dh_nb = {
.notifier_call = scsi_dh_notifier
};
Index: linux-2.6.26-git5/include/scsi/scsi_dh.h
================================================== =================
--- linux-2.6.26-git5.orig/include/scsi/scsi_dh.h
+++ linux-2.6.26-git5/include/scsi/scsi_dh.h
@@ -58,6 +58,8 @@ enum {
#if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE)
extern int scsi_dh_activate(struct request_queue *);
extern int scsi_dh_handler_exist(const char *);
+extern int scsi_dh_attach(struct request_queue *, const char *);
+extern void scsi_dh_detach(struct request_queue *);
#else
static inline int scsi_dh_activate(struct request_queue *req)
{
@@ -67,4 +69,12 @@ static inline int scsi_dh_handler_exist(
{
return 0;
}
+static inline int scsi_dh_attach(struct request_queue *req, const char *name)
+{
+ return SCSI_DH_NOSYS;
+}
+static inline void scsi_dh_detach(struct request_queue *q)
+{
+ return;
+}
#endif

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 07-18-2008, 12:08 AM
Alasdair G Kergon
 
Default scsi_dh: attach to hardware handler from dm-mpath

On Thu, Jul 17, 2008 at 04:53:27PM -0700, Chandra Seetharaman wrote:
> +++ linux-2.6.26-git5/drivers/md/dm-mpath.c
> @@ -147,9 +147,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;

> @@ -546,6 +549,7 @@ static struct pgpath *parse_path(struct
> {
> int r;
> struct pgpath *p;
> + struct multipath *m = (struct multipath *) ti->private;

FYI We're not writing explicit casts in cases like that in new dm code.

Alasdair
--
agk@redhat.com

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 

Thread Tools




All times are GMT. The time now is 06:54 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org