From patchwork Thu Oct 16 05:37:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Christie X-Patchwork-Id: 5088011 Return-Path: X-Original-To: patchwork-ceph-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 58360C11AC for ; Thu, 16 Oct 2014 05:37:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 62DF820176 for ; Thu, 16 Oct 2014 05:37:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 52D7D2016C for ; Thu, 16 Oct 2014 05:37:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751228AbaJPFhd (ORCPT ); Thu, 16 Oct 2014 01:37:33 -0400 Received: from sabe.cs.wisc.edu ([128.105.6.20]:39645 "EHLO sabe.cs.wisc.edu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751051AbaJPFhc (ORCPT ); Thu, 16 Oct 2014 01:37:32 -0400 Received: from localhost.localdomain (c-24-245-27-162.hsd1.mn.comcast.net [24.245.27.162]) (authenticated bits=0) by sabe.cs.wisc.edu (8.14.1/8.14.1) with ESMTP id s9G5bMxG012139 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 16 Oct 2014 00:37:30 -0500 From: michaelc@cs.wisc.edu To: linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, ceph-devel@vger.kernel.org, axboe@kernel.dk Subject: [PATCH 5/5] lio iblock: add support for REQ_CMP_AND_WRITE Date: Thu, 16 Oct 2014 00:37:15 -0500 Message-Id: <1413437835-13778-6-git-send-email-michaelc@cs.wisc.edu> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1413437835-13778-1-git-send-email-michaelc@cs.wisc.edu> References: <1413437835-13778-1-git-send-email-michaelc@cs.wisc.edu> Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mike Christie This patch has the iblock backing store use blkdev_issue_cmp_and_write if the backing store device/queue supports it. Signed-off-by: Mike Christie --- drivers/target/target_core_iblock.c | 85 ++++++++++++++++++++++++++++------- 1 files changed, 68 insertions(+), 17 deletions(-) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 7e6b857..cac928a 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -153,6 +153,11 @@ static int iblock_configure_device(struct se_device *dev) */ dev->dev_attrib.max_write_same_len = 0xFFFF; + /* convert from linux block layer 512 byte sector to our block size */ + dev->dev_attrib.max_compare_and_write_len = + (q->limits.max_cmp_and_write_sectors << IBLOCK_LBA_SHIFT) / + dev->dev_attrib.hw_block_size; + if (blk_queue_nonrot(q)) dev->dev_attrib.is_nonrot = 1; @@ -413,6 +418,67 @@ iblock_execute_sync_cache(struct se_cmd *cmd) return 0; } +/* + * Convert the blocksize advertised to the initiator to the 512 byte + * units unconditionally used by the Linux block layer. + */ +static int iblock_get_lba_shift(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + + if (dev->dev_attrib.block_size == 4096) + return 3; + else if (dev->dev_attrib.block_size == 2048) + return 2; + else if (dev->dev_attrib.block_size == 1024) + return 1; + else + return 0; +} + +static sense_reason_t +iblock_execute_compare_and_write(struct se_cmd *cmd) +{ + struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd; + int ret, i = 0; + sector_t block_lba; + struct scatterlist *sg; + struct bio *bio; + + block_lba = cmd->t_task_lba << iblock_get_lba_shift(cmd); + + /* assumes SGLs are PAGE_SIZE */ + bio = blkdev_setup_cmp_and_write(bdev, block_lba, GFP_KERNEL, + cmd->t_data_nents); + if (!bio) { + pr_err("blkdev_setup_cmp_and_write() failed\n"); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + + for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { + ret = bio_add_pc_page(bdev_get_queue(bdev), bio, sg_page(sg), + sg->length, sg->offset); + if (ret != sg->length) { + bio_put(bio); + pr_err("bio_add_pc_page() failed\n"); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + } + + ret = blkdev_issue_cmp_and_write(bio); + if (ret == -ECANCELED) { + pr_warn("Target/%s: Send MISCOMPARE check condition and sense\n", + cmd->se_dev->transport->name); + return TCM_MISCOMPARE_VERIFY; + } else if (ret < 0) { + pr_err("blkdev_issue_cmp_and_write() failed: %d\n", ret); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + + target_complete_cmd(cmd, GOOD); + return 0; +} + static sense_reason_t iblock_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) @@ -701,23 +767,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, rw = READ; } - /* - * Convert the blocksize advertised to the initiator to the 512 byte - * units unconditionally used by the Linux block layer. - */ - if (dev->dev_attrib.block_size == 4096) - block_lba = (cmd->t_task_lba << 3); - else if (dev->dev_attrib.block_size == 2048) - block_lba = (cmd->t_task_lba << 2); - else if (dev->dev_attrib.block_size == 1024) - block_lba = (cmd->t_task_lba << 1); - else if (dev->dev_attrib.block_size == 512) - block_lba = cmd->t_task_lba; - else { - pr_err("Unsupported SCSI -> BLOCK LBA conversion:" - " %u\n", dev->dev_attrib.block_size); - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - } + block_lba = cmd->t_task_lba << iblock_get_lba_shift(cmd); ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); if (!ibr) @@ -841,6 +891,7 @@ static struct sbc_ops iblock_sbc_ops = { .execute_write_same = iblock_execute_write_same, .execute_write_same_unmap = iblock_execute_write_same_unmap, .execute_unmap = iblock_execute_unmap, + .execute_compare_and_write = iblock_execute_compare_and_write, }; static sense_reason_t