diff options
author | Shlomo Pongratz <shlomop@mellanox.com> | 2014-02-07 01:41:37 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-15 13:19:18 -0400 |
commit | 5d0fddd0a72d3023bb0fa97e546f687aa6222be3 (patch) | |
tree | a08201b0fcf76e1efcf1be3741b5972be146c341 /drivers/scsi/libiscsi_tcp.c | |
parent | ac0245ff80942e33458cf32926dc1177239f4e19 (diff) |
[SCSI] libiscsi: Restructure iscsi_tcp r2t response logic
Restructure the iscsi_tcp_r2t_rsp routine in order to avoid allocating
r2t from r2tpool.queue and returning it back in case the parameters
rhdr->data_length and or rhdr->data_offset prohibit the requing.
Since the values of these parameters are known prior to the allocation,
we can pre-check and thus avoid futile allocations.
[jejb: checkpatch fixes]
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libiscsi_tcp.c')
-rw-r--r-- | drivers/scsi/libiscsi_tcp.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 1d58d5336018..2f738dddd078 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c | |||
@@ -529,6 +529,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) | |||
529 | struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; | 529 | struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; |
530 | struct iscsi_r2t_info *r2t; | 530 | struct iscsi_r2t_info *r2t; |
531 | int r2tsn = be32_to_cpu(rhdr->r2tsn); | 531 | int r2tsn = be32_to_cpu(rhdr->r2tsn); |
532 | u32 data_length; | ||
533 | u32 data_offset; | ||
532 | int rc; | 534 | int rc; |
533 | 535 | ||
534 | if (tcp_conn->in.datalen) { | 536 | if (tcp_conn->in.datalen) { |
@@ -554,40 +556,39 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) | |||
554 | return 0; | 556 | return 0; |
555 | } | 557 | } |
556 | 558 | ||
557 | rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); | 559 | data_length = be32_to_cpu(rhdr->data_length); |
558 | if (!rc) { | 560 | if (data_length == 0) { |
559 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. " | ||
560 | "Target has sent more R2Ts than it " | ||
561 | "negotiated for or driver has leaked.\n"); | ||
562 | return ISCSI_ERR_PROTO; | ||
563 | } | ||
564 | |||
565 | r2t->exp_statsn = rhdr->statsn; | ||
566 | r2t->data_length = be32_to_cpu(rhdr->data_length); | ||
567 | if (r2t->data_length == 0) { | ||
568 | iscsi_conn_printk(KERN_ERR, conn, | 561 | iscsi_conn_printk(KERN_ERR, conn, |
569 | "invalid R2T with zero data len\n"); | 562 | "invalid R2T with zero data len\n"); |
570 | kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, | ||
571 | sizeof(void*)); | ||
572 | return ISCSI_ERR_DATALEN; | 563 | return ISCSI_ERR_DATALEN; |
573 | } | 564 | } |
574 | 565 | ||
575 | if (r2t->data_length > session->max_burst) | 566 | if (data_length > session->max_burst) |
576 | ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max " | 567 | ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max " |
577 | "burst %u. Attempting to execute request.\n", | 568 | "burst %u. Attempting to execute request.\n", |
578 | r2t->data_length, session->max_burst); | 569 | data_length, session->max_burst); |
579 | 570 | ||
580 | r2t->data_offset = be32_to_cpu(rhdr->data_offset); | 571 | data_offset = be32_to_cpu(rhdr->data_offset); |
581 | if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) { | 572 | if (data_offset + data_length > scsi_out(task->sc)->length) { |
582 | iscsi_conn_printk(KERN_ERR, conn, | 573 | iscsi_conn_printk(KERN_ERR, conn, |
583 | "invalid R2T with data len %u at offset %u " | 574 | "invalid R2T with data len %u at offset %u " |
584 | "and total length %d\n", r2t->data_length, | 575 | "and total length %d\n", data_length, |
585 | r2t->data_offset, scsi_out(task->sc)->length); | 576 | data_offset, scsi_out(task->sc)->length); |
586 | kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, | ||
587 | sizeof(void*)); | ||
588 | return ISCSI_ERR_DATALEN; | 577 | return ISCSI_ERR_DATALEN; |
589 | } | 578 | } |
590 | 579 | ||
580 | rc = kfifo_out(&tcp_task->r2tpool.queue, (void *)&r2t, sizeof(void *)); | ||
581 | if (!rc) { | ||
582 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. " | ||
583 | "Target has sent more R2Ts than it " | ||
584 | "negotiated for or driver has leaked.\n"); | ||
585 | return ISCSI_ERR_PROTO; | ||
586 | } | ||
587 | |||
588 | r2t->exp_statsn = rhdr->statsn; | ||
589 | r2t->data_length = data_length; | ||
590 | r2t->data_offset = data_offset; | ||
591 | |||
591 | r2t->ttt = rhdr->ttt; /* no flip */ | 592 | r2t->ttt = rhdr->ttt; /* no flip */ |
592 | r2t->datasn = 0; | 593 | r2t->datasn = 0; |
593 | r2t->sent = 0; | 594 | r2t->sent = 0; |