Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libiscsi, iser: Adjust data_length to include protection information

In case protection information exists over the wire
iscsi header data length is required to include it.
Use protection information aware scsi helpers to set
the correct transfer length.

In order to avoid breakage, remove iser transfer length
checks for each task as they are not always true and
somewhat redundant anyway.

Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Acked-by: Mike Christie <michaelc@cs.wisc.edu>
Cc: stable@vger.kernel.org # 3.15+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Sagi Grimberg and committed by
Nicholas Bellinger
d77e6535 8846bab1

+19 -33
+10 -24
drivers/infiniband/ulp/iser/iser_initiator.c
··· 41 41 #include "iscsi_iser.h" 42 42 43 43 /* Register user buffer memory and initialize passive rdma 44 - * dto descriptor. Total data size is stored in 45 - * iser_task->data[ISER_DIR_IN].data_len 44 + * dto descriptor. Data size is stored in 45 + * task->data[ISER_DIR_IN].data_len, Protection size 46 + * os stored in task->prot[ISER_DIR_IN].data_len 46 47 */ 47 - static int iser_prepare_read_cmd(struct iscsi_task *task, 48 - unsigned int edtl) 48 + static int iser_prepare_read_cmd(struct iscsi_task *task) 49 49 50 50 { 51 51 struct iscsi_iser_task *iser_task = task->dd_data; ··· 73 73 return err; 74 74 } 75 75 76 - if (edtl > iser_task->data[ISER_DIR_IN].data_len) { 77 - iser_err("Total data length: %ld, less than EDTL: " 78 - "%d, in READ cmd BHS itt: %d, conn: 0x%p\n", 79 - iser_task->data[ISER_DIR_IN].data_len, edtl, 80 - task->itt, iser_task->ib_conn); 81 - return -EINVAL; 82 - } 83 - 84 76 err = device->iser_reg_rdma_mem(iser_task, ISER_DIR_IN); 85 77 if (err) { 86 78 iser_err("Failed to set up Data-IN RDMA\n"); ··· 92 100 } 93 101 94 102 /* Register user buffer memory and initialize passive rdma 95 - * dto descriptor. Total data size is stored in 96 - * task->data[ISER_DIR_OUT].data_len 103 + * dto descriptor. Data size is stored in 104 + * task->data[ISER_DIR_OUT].data_len, Protection size 105 + * is stored at task->prot[ISER_DIR_OUT].data_len 97 106 */ 98 107 static int 99 108 iser_prepare_write_cmd(struct iscsi_task *task, ··· 126 133 DMA_TO_DEVICE); 127 134 if (err) 128 135 return err; 129 - } 130 - 131 - if (edtl > iser_task->data[ISER_DIR_OUT].data_len) { 132 - iser_err("Total data length: %ld, less than EDTL: %d, " 133 - "in WRITE cmd BHS itt: %d, conn: 0x%p\n", 134 - iser_task->data[ISER_DIR_OUT].data_len, 135 - edtl, task->itt, task->conn); 136 - return -EINVAL; 137 136 } 138 137 139 138 err = device->iser_reg_rdma_mem(iser_task, ISER_DIR_OUT); ··· 402 417 if (scsi_prot_sg_count(sc)) { 403 418 prot_buf->buf = scsi_prot_sglist(sc); 404 419 prot_buf->size = scsi_prot_sg_count(sc); 405 - prot_buf->data_len = sc->prot_sdb->length; 420 + prot_buf->data_len = data_buf->data_len >> 421 + ilog2(sc->device->sector_size) * 8; 406 422 } 407 423 408 424 if (hdr->flags & ISCSI_FLAG_CMD_READ) { 409 - err = iser_prepare_read_cmd(task, edtl); 425 + err = iser_prepare_read_cmd(task); 410 426 if (err) 411 427 goto send_command_error; 412 428 }
+9 -9
drivers/scsi/libiscsi.c
··· 338 338 struct iscsi_session *session = conn->session; 339 339 struct scsi_cmnd *sc = task->sc; 340 340 struct iscsi_scsi_req *hdr; 341 - unsigned hdrlength, cmd_len; 341 + unsigned hdrlength, cmd_len, transfer_length; 342 342 itt_t itt; 343 343 int rc; 344 344 ··· 391 391 if (scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) 392 392 task->protected = true; 393 393 394 + transfer_length = scsi_transfer_length(sc); 395 + hdr->data_length = cpu_to_be32(transfer_length); 394 396 if (sc->sc_data_direction == DMA_TO_DEVICE) { 395 - unsigned out_len = scsi_out(sc)->length; 396 397 struct iscsi_r2t_info *r2t = &task->unsol_r2t; 397 398 398 - hdr->data_length = cpu_to_be32(out_len); 399 399 hdr->flags |= ISCSI_FLAG_CMD_WRITE; 400 400 /* 401 401 * Write counters: ··· 414 414 memset(r2t, 0, sizeof(*r2t)); 415 415 416 416 if (session->imm_data_en) { 417 - if (out_len >= session->first_burst) 417 + if (transfer_length >= session->first_burst) 418 418 task->imm_count = min(session->first_burst, 419 419 conn->max_xmit_dlength); 420 420 else 421 - task->imm_count = min(out_len, 422 - conn->max_xmit_dlength); 421 + task->imm_count = min(transfer_length, 422 + conn->max_xmit_dlength); 423 423 hton24(hdr->dlength, task->imm_count); 424 424 } else 425 425 zero_data(hdr->dlength); 426 426 427 427 if (!session->initial_r2t_en) { 428 - r2t->data_length = min(session->first_burst, out_len) - 428 + r2t->data_length = min(session->first_burst, 429 + transfer_length) - 429 430 task->imm_count; 430 431 r2t->data_offset = task->imm_count; 431 432 r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); ··· 439 438 } else { 440 439 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 441 440 zero_data(hdr->dlength); 442 - hdr->data_length = cpu_to_be32(scsi_in(sc)->length); 443 441 444 442 if (sc->sc_data_direction == DMA_FROM_DEVICE) 445 443 hdr->flags |= ISCSI_FLAG_CMD_READ; ··· 466 466 scsi_bidi_cmnd(sc) ? "bidirectional" : 467 467 sc->sc_data_direction == DMA_TO_DEVICE ? 468 468 "write" : "read", conn->id, sc, sc->cmnd[0], 469 - task->itt, scsi_bufflen(sc), 469 + task->itt, transfer_length, 470 470 scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, 471 471 session->cmdsn, 472 472 session->max_cmdsn - session->exp_cmdsn + 1);