]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.19.7/target-file-fix-unmap-with-dif-protection-support.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.19.7 / target-file-fix-unmap-with-dif-protection-support.patch
CommitLineData
eefdbb8e
GKH
1From 64d240b721b21e266ffde645ec965c3b6d1c551f Mon Sep 17 00:00:00 2001
2From: Akinobu Mita <akinobu.mita@gmail.com>
3Date: Mon, 13 Apr 2015 23:21:58 +0900
4Subject: target/file: Fix UNMAP with DIF protection support
5
6From: Akinobu Mita <akinobu.mita@gmail.com>
7
8commit 64d240b721b21e266ffde645ec965c3b6d1c551f upstream.
9
10When UNMAP command is issued with DIF protection support enabled,
11the protection info for the unmapped region is remain unchanged.
12So READ command for the region causes data integrity failure.
13
14This fixes it by invalidating protection info for the unmapped region
15by filling with 0xff pattern. This change also adds helper function
16fd_do_prot_fill() in order to reduce code duplication with existing
17fd_format_prot().
18
19Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
20Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
21Reviewed-by: "Martin K. Petersen" <martin.petersen@oracle.com>
22Cc: Christoph Hellwig <hch@lst.de>
23Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
24Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
25Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
26
27---
28 drivers/target/target_core_file.c | 86 ++++++++++++++++++++++++++------------
29 1 file changed, 61 insertions(+), 25 deletions(-)
30
31--- a/drivers/target/target_core_file.c
32+++ b/drivers/target/target_core_file.c
33@@ -545,6 +545,56 @@ fd_execute_write_same(struct se_cmd *cmd
34 return 0;
35 }
36
37+static int
38+fd_do_prot_fill(struct se_device *se_dev, sector_t lba, sector_t nolb,
39+ void *buf, size_t bufsize)
40+{
41+ struct fd_dev *fd_dev = FD_DEV(se_dev);
42+ struct file *prot_fd = fd_dev->fd_prot_file;
43+ sector_t prot_length, prot;
44+ loff_t pos = lba * se_dev->prot_length;
45+
46+ if (!prot_fd) {
47+ pr_err("Unable to locate fd_dev->fd_prot_file\n");
48+ return -ENODEV;
49+ }
50+
51+ prot_length = nolb * se_dev->prot_length;
52+
53+ for (prot = 0; prot < prot_length;) {
54+ sector_t len = min_t(sector_t, bufsize, prot_length - prot);
55+ ssize_t ret = kernel_write(prot_fd, buf, len, pos + prot);
56+
57+ if (ret != len) {
58+ pr_err("vfs_write to prot file failed: %zd\n", ret);
59+ return ret < 0 ? ret : -ENODEV;
60+ }
61+ prot += ret;
62+ }
63+
64+ return 0;
65+}
66+
67+static int
68+fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
69+{
70+ void *buf;
71+ int rc;
72+
73+ buf = (void *)__get_free_page(GFP_KERNEL);
74+ if (!buf) {
75+ pr_err("Unable to allocate FILEIO prot buf\n");
76+ return -ENOMEM;
77+ }
78+ memset(buf, 0xff, PAGE_SIZE);
79+
80+ rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE);
81+
82+ free_page((unsigned long)buf);
83+
84+ return rc;
85+}
86+
87 static sense_reason_t
88 fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
89 {
90@@ -552,6 +602,12 @@ fd_do_unmap(struct se_cmd *cmd, void *pr
91 struct inode *inode = file->f_mapping->host;
92 int ret;
93
94+ if (cmd->se_dev->dev_attrib.pi_prot_type) {
95+ ret = fd_do_prot_unmap(cmd, lba, nolb);
96+ if (ret)
97+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
98+ }
99+
100 if (S_ISBLK(inode->i_mode)) {
101 /* The backend is block device, use discard */
102 struct block_device *bdev = inode->i_bdev;
103@@ -874,48 +930,28 @@ static int fd_init_prot(struct se_device
104
105 static int fd_format_prot(struct se_device *dev)
106 {
107- struct fd_dev *fd_dev = FD_DEV(dev);
108- struct file *prot_fd = fd_dev->fd_prot_file;
109- sector_t prot_length, prot;
110 unsigned char *buf;
111- loff_t pos = 0;
112 int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size;
113- int rc, ret = 0, size, len;
114+ int ret;
115
116 if (!dev->dev_attrib.pi_prot_type) {
117 pr_err("Unable to format_prot while pi_prot_type == 0\n");
118 return -ENODEV;
119 }
120- if (!prot_fd) {
121- pr_err("Unable to locate fd_dev->fd_prot_file\n");
122- return -ENODEV;
123- }
124
125 buf = vzalloc(unit_size);
126 if (!buf) {
127 pr_err("Unable to allocate FILEIO prot buf\n");
128 return -ENOMEM;
129 }
130- prot_length = (dev->transport->get_blocks(dev) + 1) * dev->prot_length;
131- size = prot_length;
132
133 pr_debug("Using FILEIO prot_length: %llu\n",
134- (unsigned long long)prot_length);
135+ (unsigned long long)(dev->transport->get_blocks(dev) + 1) *
136+ dev->prot_length);
137
138 memset(buf, 0xff, unit_size);
139- for (prot = 0; prot < prot_length; prot += unit_size) {
140- len = min(unit_size, size);
141- rc = kernel_write(prot_fd, buf, len, pos);
142- if (rc != len) {
143- pr_err("vfs_write to prot file failed: %d\n", rc);
144- ret = -ENODEV;
145- goto out;
146- }
147- pos += len;
148- size -= len;
149- }
150-
151-out:
152+ ret = fd_do_prot_fill(dev, 0, dev->transport->get_blocks(dev) + 1,
153+ buf, unit_size);
154 vfree(buf);
155 return ret;
156 }