On Wed, Oct 03 2007 at 3:55 +0200, Matthew Wilcox <[EMAIL PROTECTED]> wrote:
> The narrow board used two global structures to set up a command;
> unfortunately they weren't locked, so with two boards in the machine,
> one call to queuecommand could corrupt the data being used by the other
> call to queuecommand.
> 
> Fix this by allocating asc_scsi_q on the stack (64 bytes) and using kmalloc
> for the asc_sg_head (2k)
> 
> Signed-off-by: Matthew Wilcox <[EMAIL PROTECTED]>
> ---
>  drivers/scsi/advansys.c |   88 
> +++++++++++++++++++++--------------------------
>  1 files changed, 39 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
> index 3dd7856..fd4d669 100644
> @@ -10257,12 +10240,12 @@ static int asc_build_req(asc_board_t *boardp, 
> struct scsi_cmnd *scp)
>                   dma_map_single(boardp->dev, scp->request_buffer,
>                                  scp->request_bufflen,
>                                  scp->sc_data_direction) : 0;
> -             asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
> -             asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
> +             asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
> +             asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen);
>               ASC_STATS_ADD(scp->device->host, cont_xfer,
>                             ASC_CEILING(scp->request_bufflen, 512));
> -             asc_scsi_q.q1.sg_queue_cnt = 0;
> -             asc_scsi_q.sg_head = NULL;
> +             asc_scsi_q->q1.sg_queue_cnt = 0;
> +             asc_scsi_q->sg_head = NULL;
>       } else {
>               /*
>                * CDB scatter-gather request list.
> @@ -10270,6 +10253,7 @@ static int asc_build_req(asc_board_t *boardp, struct 
> scsi_cmnd *scp)
>               int sgcnt;
>               int use_sg;
>               struct scatterlist *slp;
> +             struct asc_sg_head *asc_sg_head;
>  
>               slp = (struct scatterlist *)scp->request_buffer;
>               use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
> @@ -10287,28 +10271,31 @@ static int asc_build_req(asc_board_t *boardp, 
> struct scsi_cmnd *scp)
>  
>               ASC_STATS(scp->device->host, sg_cnt);
>  
> -             /*
> -              * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
> -              * structure to point to it.
> -              */
> -             memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
> +             asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) +
> +                     use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC);
> +             if (!asc_sg_head) {
> +                     dma_unmap_sg(boardp->dev, slp, scp->use_sg,
> +                                  scp->sc_data_direction);
> +                     scp->result = HOST_BYTE(DID_SOFT_ERROR);
> +                     return ASC_ERROR;
> +             }
>  
> -             asc_scsi_q.q1.cntl |= QC_SG_HEAD;
> -             asc_scsi_q.sg_head = &asc_sg_head;
> -             asc_scsi_q.q1.data_cnt = 0;
> -             asc_scsi_q.q1.data_addr = 0;
> +             asc_scsi_q->q1.cntl |= QC_SG_HEAD;
> +             asc_scsi_q->sg_head = asc_sg_head;
> +             asc_scsi_q->q1.data_cnt = 0;
> +             asc_scsi_q->q1.data_addr = 0;
>               /* This is a byte value, otherwise it would need to be swapped. 
> */
> -             asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
> +             asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg;
>               ASC_STATS_ADD(scp->device->host, sg_elem,
> -                           asc_sg_head.entry_cnt);
> +                           asc_sg_head->entry_cnt);
>  
>               /*
>                * Convert scatter-gather list into ASC_SG_HEAD list.
>                */
>               for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
> -                     asc_sg_head.sg_list[sgcnt].addr =
> +                     asc_sg_head->sg_list[sgcnt].addr =
>                           cpu_to_le32(sg_dma_address(slp));
> -                     asc_sg_head.sg_list[sgcnt].bytes =
> +                     asc_sg_head->sg_list[sgcnt].bytes =
>                           cpu_to_le32(sg_dma_len(slp));
>                       ASC_STATS_ADD(scp->device->host, sg_xfer,
>                                     ASC_CEILING(sg_dma_len(slp), 512));
> @@ -11338,14 +11325,17 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd 
> *scp)
>  
>       if (ASC_NARROW_BOARD(boardp)) {
>               ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
> +             struct asc_scsi_q asc_scsi_q;
>  
>               /* asc_build_req() can not return ASC_BUSY. */
> -             if (asc_build_req(boardp, scp) == ASC_ERROR) {
> +             ret = asc_build_req(boardp, scp, &asc_scsi_q);
> +             if (ret == ASC_ERROR) {
>                       ASC_STATS(scp->device->host, build_error);
>                       return ASC_ERROR;
>               }
>  
>               ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q);
> +             kfree(asc_scsi_q.sg_head);
>               err_code = asc_dvc->err_code;
>       } else {
>               ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew 
I see that these patches are before the conversion to scsi data accessors 
and !use_sg cleanup that was posted by TOMO:
http://www.spinics.net/lists/linux-scsi/msg19055.html

Could you please also post that patch rebased to latest changes as part of
your patchset?

I was hoping we could get all the data accessors patches into 2.6.24,
Is this patchset for the 2.6.24 window?

Thanks
Boaz


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to