| From 613903aadd4f0340566e361dde14598313da697b Mon Sep 17 00:00:00 2001 |
| From: Xiubo Li <lixiubo@cmss.chinamobile.com> |
| Date: Mon, 27 Mar 2017 17:07:41 +0800 |
| Subject: [PATCH] tcmu: Fix wrongly calculating of the base_command_size |
| |
| commit abe342a5b4b5aa579f6bf40ba73447c699e6b579 upstream. |
| |
| The t_data_nents and t_bidi_data_nents are the numbers of the |
| segments, but it couldn't be sure the block size equals to size |
| of the segment. |
| |
| For the worst case, all the blocks are discontiguous and there |
| will need the same number of iovecs, that's to say: blocks == iovs. |
| So here just set the number of iovs to block count needed by tcmu |
| cmd. |
| |
| Tested-by: Ilias Tsitsimpis <iliastsi@arrikto.com> |
| Reviewed-by: Mike Christie <mchristi@redhat.com> |
| Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com> |
| Cc: stable@vger.kernel.org # 3.18+ |
| Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c |
| index 2ffd4177feaa..48e29a2ed326 100644 |
| --- a/drivers/target/target_core_user.c |
| +++ b/drivers/target/target_core_user.c |
| @@ -403,6 +403,13 @@ static inline size_t tcmu_cmd_get_data_length(struct tcmu_cmd *tcmu_cmd) |
| return data_length; |
| } |
| |
| +static inline uint32_t tcmu_cmd_get_block_cnt(struct tcmu_cmd *tcmu_cmd) |
| +{ |
| + size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd); |
| + |
| + return data_length / DATA_BLOCK_SIZE; |
| +} |
| + |
| static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) |
| { |
| struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; |
| @@ -429,8 +436,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) |
| * expensive to tell how many regions are freed in the bitmap |
| */ |
| base_command_size = max(offsetof(struct tcmu_cmd_entry, |
| - req.iov[se_cmd->t_bidi_data_nents + |
| - se_cmd->t_data_nents]), |
| + req.iov[tcmu_cmd_get_block_cnt(tcmu_cmd)]), |
| sizeof(struct tcmu_cmd_entry)); |
| command_size = base_command_size |
| + round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE); |
| -- |
| 2.12.0 |
| |