[dm-devel] Re: [PATCH 1/7] scsi_dh: add skeleton for SCSI Device Handlers
Chandra Seetharaman
sekharan at us.ibm.com
Tue Mar 4 22:25:56 UTC 2008
Thanks for your comments, James.
On Tue, 2008-03-04 at 15:37 -0600, James Bottomley wrote:
> On Wed, 2008-02-27 at 17:08 -0800, Chandra Seetharaman wrote:
> > Subject: scsi_dh: add skeleton for SCSI Device Handlers
> >
> > From: Chandra Seetharaman <sekharan at us.ibm.com>
> >
> > Add base support to the SCSI subsystem for SCSI device handlers.
>
> Generally, this is much cleaner and an easier implementation to follow,
> thanks.
Cool, thanks.
>
> > Signed-off-by: Chandra Seetharaman <sekharan at us.ibm.com>
> > Signed-off-by: Mike Anderson <andmike at linux.vnet.ibm.com>
> > Signed-off-by: Mike Christie <michaelc at cs.wisc.edu>
<snip>
> if (! scsi_command_normalize_sense(scmd, &sshdr))
> > @@ -306,6 +307,15 @@ static int scsi_check_sense(struct scsi_
> > if (scsi_sense_is_deferred(&sshdr))
> > return NEEDS_RETRY;
> >
> > + if (sdev->sdev_dh && sdev->sdev_dh->check_sense) {
> > + int rc;
> > +
> > + rc = sdev->sdev_dh->check_sense(sdev, &sshdr);
> > + if (rc != SUCCESS)
>
> I can see reasons for a sense handler to return SUCCESS to trigger a
> fast failure (say not ready needs initialising command or something, so
> this should be a specific sense handler doesn't care return code.
understand. I can return a NOT_HANDLED. Is it ok to add it as 0x2008 to
scsi.h ? or any suggestions.
>
> > + return rc;
> > + /* handler does not care. Drop down to default handling */
> > + }
> > +
> > /*
> > * Previous logic looked for FILEMARK, EOM or ILI which are
> > * mainly associated with tapes and returned SUCCESS.
> > Index: linux-2.6.25-rc2-mm1/include/scsi/scsi_device.h
> > ===================================================================
> > --- linux-2.6.25-rc2-mm1.orig/include/scsi/scsi_device.h
> > +++ linux-2.6.25-rc2-mm1/include/scsi/scsi_device.h
> > @@ -161,9 +161,25 @@ struct scsi_device {
> >
> > struct execute_work ew; /* used to get process context on put */
> >
> > + struct scsi_device_handler *sdev_dh;
> > + void *sdev_dh_data;
>
> This is a bit wasteful of 8 bytes ... why not simply move the
> sdev_dh_data inside the sdev_dh structure, then if there's no handler
> it's not occupying space?
There is one sdev_dh per handler, and one sdev_dh_data per device.
But, structures can be redefined to save space when there is no hardware
handler present. But, there will be a additional pointer dereference
while invoking the functions, is it ok ?
Here is what I am thinking:
--------
struct scsi_device_handler { }; /* same as now */
struct scsi_dh_data {
struct scsi_device_handler *sdev_dh;
char buf[0];
};
and the handlers will allocate appropriate size for this data structure.
struct scsi_device {
:
:
struct scsi_dh_data *scsi_dh_data;
};
all the function invocations will be like
sdev->scsi_dh_data->sdev_dh->activate,prep_fn,check_sense
------------
>
> > enum scsi_device_state sdev_state;
> > unsigned long sdev_data[0];
> > } __attribute__((aligned(sizeof(unsigned long))));
> >
<snip>
> +int scsi_dh_activate(struct request_queue *q)
> > +{
> > + int err = SCSI_DH_NOSYS;
> > + struct scsi_device *sdev;
> > + struct scsi_device_handler *sdev_dh;
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(q->queue_lock, flags);
> > + sdev = q->queuedata;
> > + sdev_dh = sdev->sdev_dh;
> > + if (!sdev || !sdev_dh || !get_device(&sdev->sdev_gendev)) {
> > + spin_unlock_irqrestore(q->queue_lock, flags);
> > + goto done;
> > + }
> > + spin_unlock_irqrestore(q->queue_lock, flags);
>
> just on programming style, this is marginally better expressed as
>
> err = (!sdev || !sdev_dh || !get_device(&sdev->sdev_gendev)) ? SCSI_DH_NOSYS : 0;
> spin_unlock_irqrestore(q->queue_lock, flags);
>
> if (err)
> goto done; (or even return err)
>
> Just to eliminate the duplicate unlocks.
will do.
>
> > +
> > + if (sdev_dh->activate)
> > + err = sdev_dh->activate(sdev);
> > + put_device(&sdev->sdev_gendev);
> > +done:
> > + return err;
> > +}
> > +EXPORT_SYMBOL_GPL(scsi_dh_activate);
> >
<snip>
> +
> > +extern int scsi_dh_activate(struct request_queue *);
> > Index: linux-2.6.25-rc2-mm1/drivers/scsi/scsi_lib.c
> > ===================================================================
> > --- linux-2.6.25-rc2-mm1.orig/drivers/scsi/scsi_lib.c
> > +++ linux-2.6.25-rc2-mm1/drivers/scsi/scsi_lib.c
> > @@ -1156,6 +1156,11 @@ int scsi_setup_fs_cmnd(struct scsi_devic
> > struct scsi_cmnd *cmd;
> > int ret = scsi_prep_state_check(sdev, req);
> >
> > + if ((ret == BLKPREP_OK) && (req->cmd_type == REQ_TYPE_FS)) {
> > + if (sdev->sdev_dh && sdev->sdev_dh->prep_fn)
> > + ret = sdev->sdev_dh->prep_fn(sdev);
> > + }
> > +
> > if (ret != BLKPREP_OK)
> > return ret;
>
> This is the fastpath and we need to be careful. We already checked
> cmd_type == REQ_TYPE before calling scsi_setup_fs_cmnd(), so there's no
> need to check it again, surely.
Yeah, this was a cut-n-paste problem. I had this block at the higher
level, moved it here to get rid of that check, but forgot to remove
that :)
>
> Plus, since we're doing if (ret != BLKPREP_OK) just below this, if you
> move the if down below that, it can simply become
>
> if (unlikely(sdev->sdev_dh && sdev->sdev_dh->prep_fn)) {
> ret = sdev->sdev_dh->prep_fn(sdev);
> if (ret != BLKPREP_OK)
> return ret;
> }
>
> Because the two outer gates have already been checked. The unlikely
> expresses the fact that having device handlers isn't currently the very
> common case.
will do.
>
> Presumably the gcc optimiser would see all of this, but it never hurts
> to make sure.
>
> James
>
>
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan at us.ibm.com | .......you may get it.
----------------------------------------------------------------------
More information about the dm-devel
mailing list