From patchwork Thu May 24 16:49:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bodo Stroesser X-Patchwork-Id: 10425183 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 288E160545 for ; Thu, 24 May 2018 16:51:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1A17C29858 for ; Thu, 24 May 2018 16:51:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 18B0F2980D; Thu, 24 May 2018 16:51:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7762429811 for ; Thu, 24 May 2018 16:50:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1033918AbeEXQuv (ORCPT ); Thu, 24 May 2018 12:50:51 -0400 Received: from mail1.bemta5.messagelabs.com ([195.245.231.143]:22568 "EHLO mail1.bemta5.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1033917AbeEXQus (ORCPT ); Thu, 24 May 2018 12:50:48 -0400 Received: from [85.158.136.83] (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256 bits)) by server-7.bemta-5.messagelabs.com id 74/A6-25237-56DE60B5; Thu, 24 May 2018 16:50:45 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupmkeJIrShJLcpLzFFi42Kxs+EI0U19yxZ tsPoPn0X39R1sFq1L3zI5MHl83iQXwBjFmpmXlF+RwJqx9/4RpoKfJhVd2zawNDAe1e5i5OIQ EljCKLHzSzM7hNPBKHHt6wYgh5ODRUBVov38H1YQm01AX6J1zXw2EFtEIEHiTNsnZhCbWcBH4 urcW2D1wgJGEuvfdoLV8Ao4Ssx52gwWFxVQk3h8fDcTRFxQ4uTMJywQvVoSN/69ZIKw5SW2v5 3DPIGRZxaSsllIymYhKVvAyLyKUaM4tagstUjXyFIvqSgzPaMkNzEzR9fQwFQvN7W4ODE9NSc xqVgvOT93EyMwkOoZGBh3MF7e4neIUZKDSUmUl+EVW7QQX1J+SmVGYnFGfFFpTmrxIUYZDg4l Cd6fr4FygkWp6akVaZk5wJCGSUtw8CiJ8P4FSfMWFyTmFmemQ6ROMSpKifNuBEkIgCQySvPg2 mBxdIlRVkqYl5GBgUGIpyC1KDezBFX+FaM4B6OSMK/tG6ApPJl5JXDTXwEtZgJafHE5M8jikk SElFQDY6+9kr3szh9TKp5e2nTg5SuX0F3lT54uE9pi1nMvN+a9/WGvqlnPfvCEdi9nu8278ll L6vttIinzuY1P+oTc+iy4SZJDtnL137kLw+2XXLkrvfNeQd23qWfrNMoOy+1z9Kps2r98z94o MXXZT2Eu4jFTZb5Mn9dT++mbgFXMw+5/ETyrXj+QKldiKc5INNRiLipOBABAvjarngIAAA== X-Env-Sender: bstroesser@ts.fujitsu.com X-Msg-Ref: server-13.tower-36.messagelabs.com!1527180645!119153317!1 X-Originating-IP: [62.60.8.84] X-SYMC-ESS-Client-Auth: outbound-route-from=pass X-StarScan-Received: X-StarScan-Version: 9.9.15; banners=-,-,- X-VirusChecked: Checked Received: (qmail 31026 invoked from network); 24 May 2018 16:50:45 -0000 Received: from unknown (HELO mailhost3.uk.fujitsu.com) (62.60.8.84) by server-13.tower-36.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 24 May 2018 16:50:45 -0000 Received: from abgdgate50u.abg.fsc.net ([172.25.138.66]) by mailhost3.uk.fujitsu.com (8.14.5/8.14.5) with ESMTP id w4OGnfFi026712; Thu, 24 May 2018 17:49:41 +0100 Received: from unknown (HELO BodoDevel.test.fsc.net) ([172.17.80.59]) by abgdgate50u.abg.fsc.net with SMTP; 24 May 2018 18:49:41 +0200 Date: Thu, 24 May 2018 18:49:41 +0200 From: Bodo Stroesser To: linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, martin.petersen@oracle.com Cc: lduncan@suse.com, hare@suse.de, mchristi@redhat.com, nab@linux-iscsi.org Subject: [RESEND] TCMUser: add read length support Message-ID: <5b06ed25.3Xi5BduJFP9OUO6V%bstroesser@ts.fujitsu.com> User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Sender: target-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: target-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is patch version 3. Generally target core and TCMUser seem to work fine for tape devices and media changers. But there is at least one situation, where TCMUser is not able to support sequential access device emulation correctly. The situation is when an initiator sends a SCSI READ CDB with a length that is greater than the length of the tape block to read. We can distinguish two subcases: A) The initiator sent the READ CDB with the SILI bit being set. In this case the sequential access device has to transfer the data from the tape block (only the length of the tape block) and transmit a good status. The current interface between TCMUser and the userspace does not support reduction of the read data size by the userspace program. The patch below fixes this subcase by allowing the userspace program to specify a reduced data size in read direction. B) The initiator sent the READ CDB with the SILI bit not being set. In this case the sequential access device has to transfer the data from the tape block as in A), but additionally has to transmit CHECK CONDITION with the ILI bit set and NO SENSE in the sensebytes. The information field in the sensebytes must contain the residual count. With the below patch a user space program can specify the real read data length and appropriate sensebytes. TCMUser then uses the se_cmd flag SCF_TREAT_READ_AS_NORMAL, to force target core to transmit the real data size and the sensebytes. Note: the flag SCF_TREAT_READ_AS_NORMAL is introduced by Lee Duncan's patch "[PATCH v4] target: transport should handle st FM/EOM/ILI reads" from Tue, 15 May 2018 18:25:24 -0700. This patch was created for kernel 4.15.9. Changes from RFC: - patch now uses SCF_TREAT_READ_AS_NORMAL to fix B) also. - comment changed accordingly Changes from V2: - Cleaned up code according to review - Userspace can set read_len for data in only, not for bidi. - read_len from userspace no longer is checked implicitly by gather_data_area(), but the check is done explicitly in tcmu_handle_completion(). Now code is easier to understand. Signed-off-by: Bodo Stroesser Acked-by: Mike Christie Reviewed-by: Lee Duncan --- include/uapi/linux/target_core_user.h | 4 ++- drivers/target/target_core_user.c | 44 +++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 9 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- a/include/uapi/linux/target_core_user.h +++ b/include/uapi/linux/target_core_user.h @@ -43,6 +43,7 @@ #define TCMU_MAILBOX_VERSION 2 #define ALIGN_SIZE 64 /* Should be enough for most CPUs */ #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */ +#define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1) /* Read data length */ struct tcmu_mailbox { __u16 version; @@ -70,6 +71,7 @@ struct tcmu_cmd_entry_hdr { __u16 cmd_id; __u8 kflags; #define TCMU_UFLAG_UNKNOWN_OP 0x1 +#define TCMU_UFLAG_READ_LEN 0x2 __u8 uflags; } __packed; @@ -118,7 +120,7 @@ struct tcmu_cmd_entry { __u8 scsi_status; __u8 __pad1; __u16 __pad2; - __u32 __pad3; + __u32 read_len; char sense_buffer[TCMU_SENSE_BUFFERSIZE]; } rsp; }; --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -576,7 +576,7 @@ static int scatter_data_area(struct tcmu } static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, - bool bidi) + bool bidi, uint32_t read_len) { struct se_cmd *se_cmd = cmd->se_cmd; int i, dbi; @@ -609,7 +609,7 @@ static void gather_data_area(struct tcmu for_each_sg(data_sg, sg, data_nents, i) { int sg_remaining = sg->length; to = kmap_atomic(sg_page(sg)) + sg->offset; - while (sg_remaining > 0) { + while (sg_remaining > 0 && read_len > 0) { if (block_remaining == 0) { if (from) kunmap_atomic(from); @@ -621,6 +621,8 @@ static void gather_data_area(struct tcmu } copy_bytes = min_t(size_t, sg_remaining, block_remaining); + if (read_len < copy_bytes) + copy_bytes = read_len; offset = DATA_BLOCK_SIZE - block_remaining; tcmu_flush_dcache_range(from, copy_bytes); memcpy(to + sg->length - sg_remaining, from + offset, @@ -628,8 +630,11 @@ static void gather_data_area(struct tcmu sg_remaining -= copy_bytes; block_remaining -= copy_bytes; + read_len -= copy_bytes; } kunmap_atomic(to - sg->offset); + if (read_len == 0) + break; } if (from) kunmap_atomic(from); @@ -947,6 +952,8 @@ static void tcmu_handle_completion(struc { struct se_cmd *se_cmd = cmd->se_cmd; struct tcmu_dev *udev = cmd->tcmu_dev; + bool read_len_valid = false; + uint32_t read_len = se_cmd->data_length; /* * cmd has been completed already from timeout, just reclaim @@ -961,13 +968,28 @@ static void tcmu_handle_completion(struc pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n", cmd->se_cmd); entry->rsp.scsi_status = SAM_STAT_CHECK_CONDITION; - } else if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) { + goto done; + } + + if (se_cmd->data_direction == DMA_FROM_DEVICE && + (entry->hdr.uflags & TCMU_UFLAG_READ_LEN) && entry->rsp.read_len) { + read_len_valid = true; + if (entry->rsp.read_len < read_len) + read_len = entry->rsp.read_len; + } + + if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) { transport_copy_sense_to_cmd(se_cmd, entry->rsp.sense_buffer); - } else if (se_cmd->se_cmd_flags & SCF_BIDI) { + if (!read_len_valid ) + goto done; + else + se_cmd->se_cmd_flags |= SCF_TREAT_READ_AS_NORMAL; + } + if (se_cmd->se_cmd_flags & SCF_BIDI) { /* Get Data-In buffer before clean up */ - gather_data_area(udev, cmd, true); + gather_data_area(udev, cmd, true, read_len); } else if (se_cmd->data_direction == DMA_FROM_DEVICE) { - gather_data_area(udev, cmd, false); + gather_data_area(udev, cmd, false, read_len); } else if (se_cmd->data_direction == DMA_TO_DEVICE) { /* TODO: */ } else if (se_cmd->data_direction != DMA_NONE) { @@ -975,7 +997,13 @@ static void tcmu_handle_completion(struc se_cmd->data_direction); } - target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status); +done: + if (read_len_valid) { + pr_debug("read_len = %d\n", read_len); + target_complete_cmd_with_length(cmd->se_cmd, + entry->rsp.scsi_status, read_len); + } else + target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status); out: cmd->se_cmd = NULL; @@ -1532,7 +1560,7 @@ static int tcmu_configure_device(struct /* Initialise the mailbox of the ring buffer */ mb = udev->mb_addr; mb->version = TCMU_MAILBOX_VERSION; - mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC; + mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC | TCMU_MAILBOX_FLAG_CAP_READ_LEN; mb->cmdr_off = CMDR_OFF; mb->cmdr_size = udev->cmdr_size;