From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sagi Grimberg Subject: Re: [PATCH 9/9] target: Enable READ_STRIP emulation in target_complete_ok_work Date: Mon, 07 Apr 2014 10:49:51 +0300 Message-ID: <5342589F.6030904@dev.mellanox.co.il> References: <1396517753-23546-1-git-send-email-nab@daterainc.com> <1396517753-23546-10-git-send-email-nab@daterainc.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1396517753-23546-10-git-send-email-nab@daterainc.com> Sender: target-devel-owner@vger.kernel.org To: "Nicholas A. Bellinger" , target-devel Cc: linux-scsi , "Martin K. Petersen" , Sagi Grimberg , Or Gerlitz , Quinn Tran , Giridhar Malavali , Nicholas Bellinger List-Id: linux-scsi@vger.kernel.org On 4/3/2014 12:35 PM, Nicholas A. Bellinger wrote: > From: Nicholas Bellinger > > This patch enables the use of READ_STRIP software emulation in > target_complete_ok_work() code for I/O READs. > > This is useful when the fabric does not support READ_STRIP hardware > offload, but would still like to interact with backend device > that have T10 PI enabled. > > Cc: Martin K. Petersen > Cc: Sagi Grimberg > Cc: Or Gerlitz > Cc: Quinn Tran > Cc: Giridhar Malavali > Signed-off-by: Nicholas Bellinger > --- > drivers/target/target_core_transport.c | 33 ++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c > index 530a9e8..a184103 100644 > --- a/drivers/target/target_core_transport.c > +++ b/drivers/target/target_core_transport.c > @@ -1905,6 +1905,24 @@ static void transport_handle_queue_full( > schedule_work(&cmd->se_dev->qf_work_queue); > } > > +static bool target_check_read_strip(struct se_cmd *cmd) > +{ > + sense_reason_t rc; > + > + if (cmd->prot_op != TARGET_PROT_DIN_STRIP) > + return false; > + > + if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_STRIP)) { > + rc = sbc_dif_read_strip(cmd); > + if (rc) { > + cmd->pi_err = rc; > + return true; > + } > + } > + > + return false; > +} > + > static void target_complete_ok_work(struct work_struct *work) > { > struct se_cmd *cmd = container_of(work, struct se_cmd, work); > @@ -1969,6 +1987,21 @@ static void target_complete_ok_work(struct work_struct *work) > cmd->data_length; > } > spin_unlock(&cmd->se_lun->lun_sep_lock); > + /* > + * Perform READ_STRIP of PI using software emulation when > + * backend had PI enabled, if the transport will not be > + * performing hardware READ_STRIP offload. > + */ You always call read_strip() even if the operation is not READ_STRIP (the routine won't do anything in this case). Personally, I usually prefer to avoid calling a routine rather then calling it and perform the checks there. I suggest: if (cmd->prot_op == TARGET_PROT_DIN_STRIP && target_check_read_strip(cmd)) { ret = transport_send_check_condition_and_sense(cmd, cmd->pi_err, 0); ... } > + if (target_check_read_strip(cmd)) { > + ret = transport_send_check_condition_and_sense(cmd, > + cmd->pi_err, 0); > + if (ret == -EAGAIN || ret == -ENOMEM) > + goto queue_full; > + > + transport_lun_remove_cmd(cmd); > + transport_cmd_check_stop_to_fabric(cmd); > + return; > + } > > trace_target_cmd_complete(cmd); > ret = cmd->se_tfo->queue_data_in(cmd);