From patchwork Mon Apr 13 14:21:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 6209911 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E227B9F1AC for ; Mon, 13 Apr 2015 14:22:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CE25D2021F for ; Mon, 13 Apr 2015 14:22:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AC37A201D3 for ; Mon, 13 Apr 2015 14:22:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932263AbbDMOWV (ORCPT ); Mon, 13 Apr 2015 10:22:21 -0400 Received: from mail-pa0-f43.google.com ([209.85.220.43]:34806 "EHLO mail-pa0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932131AbbDMOWU (ORCPT ); Mon, 13 Apr 2015 10:22:20 -0400 Received: by pacyx8 with SMTP id yx8so103698278pac.1; Mon, 13 Apr 2015 07:22:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MmYFaVt0UJTDXYyX50oHn3YMSBsiaoFDvo258VnozIU=; b=SE7Y3cUfLJVLrL6YHcOAbDcR1DGqwxuvRNtwgpJ8tgvoLmBbEoT/AJIEKc757bJbsL YR4K/1tRfTva5A1IxmgX3Sv3Pux80rmAXU6siu2WIBL2l6NXF4KQQ0LNMlWmA7pxHFb9 /zwFgh3BPOxyx523RZoTaMONHkBdBbapf5oHveDHxrUwFswC7hsrv2yiE7txmV/95Hkj BZad2h2GAdkIXk1enDY7sTcH6575uWxzcsBqK2NyvZDGKonywmUlC4XZnulCoYUBArtz s3D+A0P+fQeHJALws9mHAjs2b0F+Rb4WFutJavVDMtELrA6zK6P2O6rdj989eEEtlqNf tkow== X-Received: by 10.66.100.165 with SMTP id ez5mr27047754pab.153.1428934939849; Mon, 13 Apr 2015 07:22:19 -0700 (PDT) Received: from localhost.localdomain (KD106168100169.ppp-bb.dion.ne.jp. [106.168.100.169]) by mx.google.com with ESMTPSA id op4sm7454078pbb.77.2015.04.13.07.22.16 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 13 Apr 2015 07:22:18 -0700 (PDT) From: Akinobu Mita To: target-devel@vger.kernel.org Cc: Akinobu Mita , Nicholas Bellinger , Sagi Grimberg , "Martin K. Petersen" , Christoph Hellwig , "James E.J. Bottomley" , linux-scsi@vger.kernel.org Subject: [PATCH 3/3] target/file: Fix UNMAP with DIF protection support Date: Mon, 13 Apr 2015 23:21:58 +0900 Message-Id: <1428934918-4004-3-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1428934918-4004-1-git-send-email-akinobu.mita@gmail.com> References: <1428934918-4004-1-git-send-email-akinobu.mita@gmail.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 When UNMAP command is issued with DIF protection support enabled, the protection info for the unmapped region is remain unchanged. So READ command for the region causes data integrity failure. This fixes it by invalidating protection info for the unmapped region by filling with 0xff pattern. This change also adds helper function fd_do_prot_fill() in order to reduce code duplication with existing fd_format_prot(). Signed-off-by: Akinobu Mita Cc: Nicholas Bellinger Cc: Sagi Grimberg Cc: "Martin K. Petersen" Cc: Christoph Hellwig Cc: "James E.J. Bottomley" Cc: target-devel@vger.kernel.org Cc: linux-scsi@vger.kernel.org Reviewed-by: Sagi Grimberg Reviewed-by: Martin K. Petersen --- drivers/target/target_core_file.c | 86 +++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 4c7a6c8..cbb0cc2 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -541,6 +541,56 @@ fd_execute_write_same(struct se_cmd *cmd) return 0; } +static int +fd_do_prot_fill(struct se_device *se_dev, sector_t lba, sector_t nolb, + void *buf, size_t bufsize) +{ + struct fd_dev *fd_dev = FD_DEV(se_dev); + struct file *prot_fd = fd_dev->fd_prot_file; + sector_t prot_length, prot; + loff_t pos = lba * se_dev->prot_length; + + if (!prot_fd) { + pr_err("Unable to locate fd_dev->fd_prot_file\n"); + return -ENODEV; + } + + prot_length = nolb * se_dev->prot_length; + + for (prot = 0; prot < prot_length;) { + sector_t len = min_t(sector_t, bufsize, prot_length - prot); + ssize_t ret = kernel_write(prot_fd, buf, len, pos + prot); + + if (ret != len) { + pr_err("vfs_write to prot file failed: %zd\n", ret); + return ret < 0 ? ret : -ENODEV; + } + prot += ret; + } + + return 0; +} + +static int +fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb) +{ + void *buf; + int rc; + + buf = (void *)__get_free_page(GFP_KERNEL); + if (!buf) { + pr_err("Unable to allocate FILEIO prot buf\n"); + return -ENOMEM; + } + memset(buf, 0xff, PAGE_SIZE); + + rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE); + + free_page((unsigned long)buf); + + return rc; +} + static sense_reason_t fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) { @@ -548,6 +598,12 @@ fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) struct inode *inode = file->f_mapping->host; int ret; + if (cmd->se_dev->dev_attrib.pi_prot_type) { + ret = fd_do_prot_unmap(cmd, lba, nolb); + if (ret) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + if (S_ISBLK(inode->i_mode)) { /* The backend is block device, use discard */ struct block_device *bdev = inode->i_bdev; @@ -870,48 +926,28 @@ static int fd_init_prot(struct se_device *dev) static int fd_format_prot(struct se_device *dev) { - struct fd_dev *fd_dev = FD_DEV(dev); - struct file *prot_fd = fd_dev->fd_prot_file; - sector_t prot_length, prot; unsigned char *buf; - loff_t pos = 0; int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size; - int rc, ret = 0, size, len; + int ret; if (!dev->dev_attrib.pi_prot_type) { pr_err("Unable to format_prot while pi_prot_type == 0\n"); return -ENODEV; } - if (!prot_fd) { - pr_err("Unable to locate fd_dev->fd_prot_file\n"); - return -ENODEV; - } buf = vzalloc(unit_size); if (!buf) { pr_err("Unable to allocate FILEIO prot buf\n"); return -ENOMEM; } - prot_length = (dev->transport->get_blocks(dev) + 1) * dev->prot_length; - size = prot_length; pr_debug("Using FILEIO prot_length: %llu\n", - (unsigned long long)prot_length); + (unsigned long long)(dev->transport->get_blocks(dev) + 1) * + dev->prot_length); memset(buf, 0xff, unit_size); - for (prot = 0; prot < prot_length; prot += unit_size) { - len = min(unit_size, size); - rc = kernel_write(prot_fd, buf, len, pos); - if (rc != len) { - pr_err("vfs_write to prot file failed: %d\n", rc); - ret = -ENODEV; - goto out; - } - pos += len; - size -= len; - } - -out: + ret = fd_do_prot_fill(dev, 0, dev->transport->get_blocks(dev) + 1, + buf, unit_size); vfree(buf); return ret; }