summaryrefslogtreecommitdiff
path: root/drivers/target
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2015-04-13 23:21:56 +0900
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-06 21:59:17 +0200
commit7623cb5297ddd7a40536012d98945b4701c84a4a (patch)
tree7681dcb602e7d5b90a59749c810809d70e54dacc /drivers/target
parentb2c9f833b0383d686160e365e0487fbd2faa3d21 (diff)
target/file: Fix BUG() when CONFIG_DEBUG_SG=y and DIF protection enabled
commit 38da0f49e8aa1649af397d53f88e163d0e60c058 upstream. When CONFIG_DEBUG_SG=y and DIF protection support enabled, kernel BUG()s are triggered due to the following two issues: 1) prot_sg is not initialized by sg_init_table(). When CONFIG_DEBUG_SG=y, scatterlist helpers check sg entry has a correct magic value. 2) vmalloc'ed buffer is passed to sg_set_buf(). sg_set_buf() uses virt_to_page() to convert virtual address to struct page, but it doesn't work with vmalloc address. vmalloc_to_page() should be used instead. As prot_buf isn't usually too large, so fix it by allocating prot_buf by kmalloc instead of vmalloc. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Sagi Grimberg <sagig@mellanox.com> Cc: "Martin K. Petersen" <martin.petersen@oracle.com> Cc: Christoph Hellwig <hch@lst.de> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_file.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 41eff7d64cb8..358e3c25b8c1 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -273,7 +273,7 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
se_dev->prot_length;
if (!is_write) {
- fd_prot->prot_buf = vzalloc(prot_size);
+ fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL);
if (!fd_prot->prot_buf) {
pr_err("Unable to allocate fd_prot->prot_buf\n");
return -ENOMEM;
@@ -285,9 +285,10 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
fd_prot->prot_sg_nents, GFP_KERNEL);
if (!fd_prot->prot_sg) {
pr_err("Unable to allocate fd_prot->prot_sg\n");
- vfree(fd_prot->prot_buf);
+ kfree(fd_prot->prot_buf);
return -ENOMEM;
}
+ sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents);
size = prot_size;
for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) {
@@ -317,7 +318,7 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
if (is_write || ret < 0) {
kfree(fd_prot->prot_sg);
- vfree(fd_prot->prot_buf);
+ kfree(fd_prot->prot_buf);
}
return ret;
@@ -652,11 +653,11 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
0, fd_prot.prot_sg, 0);
if (rc) {
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
return rc;
}
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
}
} else {
memset(&fd_prot, 0, sizeof(struct fd_prot));
@@ -672,7 +673,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
0, fd_prot.prot_sg, 0);
if (rc) {
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
return rc;
}
}
@@ -703,7 +704,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
if (ret < 0) {
kfree(fd_prot.prot_sg);
- vfree(fd_prot.prot_buf);
+ kfree(fd_prot.prot_buf);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}