lkml.org 
[lkml]   [2014]   [Jan]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 13/14] target/rd: Add DIF protection into rd_execute_rw
    On 1/8/2014 10:36 PM, Nicholas A. Bellinger wrote:
    > From: Nicholas Bellinger <nab@linux-iscsi.org>
    >
    > This patch adds support for DIF protection into rd_execute_rw() code
    > for WRITE/READ I/O using sbc_dif_verify_[write,read]() logic.
    >
    > It also adds rd_get_prot_table() for locating protection SGLs
    > assoicated with the ramdisk backend device.
    >
    > Cc: Martin K. Petersen <martin.petersen@oracle.com>
    > Cc: Christoph Hellwig <hch@lst.de>
    > Cc: Hannes Reinecke <hare@suse.de>
    > Cc: Sagi Grimberg <sagig@mellanox.com>
    > Cc: Or Gerlitz <ogerlitz@mellanox.com>
    > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
    > ---
    > drivers/target/target_core_rd.c | 67 +++++++++++++++++++++++++++++++++++++++
    > 1 file changed, 67 insertions(+)
    >
    > diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
    > index dd99844..3fd51eb 100644
    > --- a/drivers/target/target_core_rd.c
    > +++ b/drivers/target/target_core_rd.c
    > @@ -363,6 +363,26 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
    > return NULL;
    > }
    >
    > +static struct rd_dev_sg_table *rd_get_prot_table(struct rd_dev *rd_dev, u32 page)
    > +{
    > + struct rd_dev_sg_table *sg_table;
    > + u32 i, sg_per_table = (RD_MAX_ALLOCATION_SIZE /
    > + sizeof(struct scatterlist));
    > +
    > + i = page / sg_per_table;
    > + if (i < rd_dev->sg_prot_count) {
    > + sg_table = &rd_dev->sg_prot_array[i];
    > + if ((sg_table->page_start_offset <= page) &&
    > + (sg_table->page_end_offset >= page))
    > + return sg_table;
    > + }
    > +
    > + pr_err("Unable to locate struct prot rd_dev_sg_table for page: %u\n",
    > + page);
    > +
    > + return NULL;
    > +}
    > +
    > static sense_reason_t
    > rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
    > enum dma_data_direction data_direction)
    > @@ -377,6 +397,7 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
    > u32 rd_page;
    > u32 src_len;
    > u64 tmp;
    > + sense_reason_t rc;
    >
    > if (dev->rd_flags & RDF_NULLIO) {
    > target_complete_cmd(cmd, SAM_STAT_GOOD);
    > @@ -399,6 +420,29 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
    > data_direction == DMA_FROM_DEVICE ? "Read" : "Write",
    > cmd->t_task_lba, rd_size, rd_page, rd_offset);
    >
    > + if ((cmd->se_cmd_flags & SCF_PROT) && se_dev->dev_attrib.pi_prot_type &&
    > + data_direction == DMA_TO_DEVICE) {
    > + sector_t sector = cmd->data_length / se_dev->dev_attrib.block_size;
    > + struct rd_dev_sg_table *prot_table;
    > + struct scatterlist *prot_sg;
    > + u32 prot_offset, prot_page;
    > +
    > + tmp = cmd->t_task_lba * se_dev->prot_length;
    > + prot_offset = do_div(tmp, PAGE_SIZE);
    > + prot_page = tmp;
    > +
    > + prot_table = rd_get_prot_table(dev, prot_page);
    > + if (!prot_table)
    > + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
    > +
    > + prot_sg = &prot_table->sg_table[prot_page - prot_table->page_start_offset];
    > +
    > + rc = sbc_dif_verify_write(cmd, cmd->t_task_lba, sector, 0,
    > + prot_sg, prot_offset);
    > + if (rc)
    > + return rc;
    > + }
    > +
    > src_len = PAGE_SIZE - rd_offset;
    > sg_miter_start(&m, sgl, sgl_nents,
    > data_direction == DMA_FROM_DEVICE ?
    > @@ -460,6 +504,29 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
    > }
    > sg_miter_stop(&m);
    >
    > + if ((cmd->se_cmd_flags & SCF_PROT) && se_dev->dev_attrib.pi_prot_type &&
    > + data_direction == DMA_FROM_DEVICE) {
    > + sector_t sector = cmd->data_length / se_dev->dev_attrib.block_size;
    > + struct rd_dev_sg_table *prot_table;
    > + struct scatterlist *prot_sg;
    > + u32 prot_offset, prot_page;
    > +
    > + tmp = cmd->t_task_lba * se_dev->prot_length;
    > + prot_offset = do_div(tmp, PAGE_SIZE);
    > + prot_page = tmp;
    > +
    > + prot_table = rd_get_prot_table(dev, prot_page);
    > + if (!prot_table)
    > + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
    > +
    > + prot_sg = &prot_table->sg_table[prot_page - prot_table->page_start_offset];
    > +
    > + rc = sbc_dif_verify_read(cmd, cmd->t_task_lba, sector, 0,
    > + prot_sg, prot_offset);
    > + if (rc)
    > + return rc;
    > + }
    > +
    > target_complete_cmd(cmd, SAM_STAT_GOOD);
    > return 0;
    > }

    I wander how we can skip sbc_dif_verify_xxxx if the transport already
    offloaded DIF verify.
    I think that the transport should signal the core layer that it is able
    to offload DIF (ADD/STRIP/PASS/VERIFY), in which case the core should
    turn off the backstore DIF verify emulation to sustain performance. I
    assume that if backstore DIF verify is offloaded as well it does not
    really matter.

    Sagi.


    \
     
     \ /
      Last update: 2014-01-09 12:01    [W:4.449 / U:0.420 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site