ctl_frontend_iscsi.c (313362) | ctl_frontend_iscsi.c (313364) |
---|---|
1/*- 2 * Copyright (c) 2012 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Edward Tomasz Napierala under sponsorship 6 * from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * | 1/*- 2 * Copyright (c) 2012 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Edward Tomasz Napierala under sponsorship 6 * from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $FreeBSD: stable/11/sys/cam/ctl/ctl_frontend_iscsi.c 313362 2017-02-07 01:38:48Z mav $ | 29 * $FreeBSD: stable/11/sys/cam/ctl/ctl_frontend_iscsi.c 313364 2017-02-07 01:42:13Z mav $ |
30 */ 31 32/* 33 * CTL frontend for the iSCSI protocol. 34 */ 35 36#include <sys/cdefs.h> | 30 */ 31 32/* 33 * CTL frontend for the iSCSI protocol. 34 */ 35 36#include <sys/cdefs.h> |
37__FBSDID("$FreeBSD: stable/11/sys/cam/ctl/ctl_frontend_iscsi.c 313362 2017-02-07 01:38:48Z mav $"); | 37__FBSDID("$FreeBSD: stable/11/sys/cam/ctl/ctl_frontend_iscsi.c 313364 2017-02-07 01:42:13Z mav $"); |
38 39#include <sys/param.h> 40#include <sys/capsicum.h> 41#include <sys/condvar.h> 42#include <sys/endian.h> 43#include <sys/file.h> 44#include <sys/kernel.h> 45#include <sys/kthread.h> --- 718 unchanged lines hidden (view full) --- 764 if (copy_len > cdw->cdw_sg_len) 765 copy_len = cdw->cdw_sg_len; 766 767 icl_pdu_get_data(request, off, cdw->cdw_sg_addr, copy_len); 768 cdw->cdw_sg_addr += copy_len; 769 cdw->cdw_sg_len -= copy_len; 770 off += copy_len; 771 io->scsiio.ext_data_filled += copy_len; | 38 39#include <sys/param.h> 40#include <sys/capsicum.h> 41#include <sys/condvar.h> 42#include <sys/endian.h> 43#include <sys/file.h> 44#include <sys/kernel.h> 45#include <sys/kthread.h> --- 718 unchanged lines hidden (view full) --- 764 if (copy_len > cdw->cdw_sg_len) 765 copy_len = cdw->cdw_sg_len; 766 767 icl_pdu_get_data(request, off, cdw->cdw_sg_addr, copy_len); 768 cdw->cdw_sg_addr += copy_len; 769 cdw->cdw_sg_len -= copy_len; 770 off += copy_len; 771 io->scsiio.ext_data_filled += copy_len; |
772 io->scsiio.kern_data_resid -= copy_len; |
|
772 773 if (cdw->cdw_sg_len == 0) { 774 /* 775 * End of current segment. 776 */ 777 if (cdw->cdw_sg_index == ctl_sg_count - 1) { 778 /* 779 * Last segment in scatter/gather list. --- 1720 unchanged lines hidden (view full) --- 2500 icl_pdu_free(response); 2501 ctl_set_busy(&io->scsiio); 2502 io->scsiio.be_move_done(io); 2503 cfiscsi_session_terminate(cs); 2504 return; 2505 } 2506 sg_addr += len; 2507 sg_len -= len; | 773 774 if (cdw->cdw_sg_len == 0) { 775 /* 776 * End of current segment. 777 */ 778 if (cdw->cdw_sg_index == ctl_sg_count - 1) { 779 /* 780 * Last segment in scatter/gather list. --- 1720 unchanged lines hidden (view full) --- 2501 icl_pdu_free(response); 2502 ctl_set_busy(&io->scsiio); 2503 io->scsiio.be_move_done(io); 2504 cfiscsi_session_terminate(cs); 2505 return; 2506 } 2507 sg_addr += len; 2508 sg_len -= len; |
2509 io->scsiio.kern_data_resid -= len; |
|
2508 2509 KASSERT(buffer_offset + response->ip_data_len <= expected_len, 2510 ("buffer_offset %zd + ip_data_len %zd > expected_len %zd", 2511 buffer_offset, response->ip_data_len, expected_len)); 2512 if (buffer_offset + response->ip_data_len == expected_len) { 2513 /* 2514 * Already have the amount of data the initiator wanted. 2515 */ --- 69 unchanged lines hidden (view full) --- 2585cfiscsi_datamove_out(union ctl_io *io) 2586{ 2587 struct cfiscsi_session *cs; 2588 struct icl_pdu *request, *response; 2589 const struct iscsi_bhs_scsi_command *bhssc; 2590 struct iscsi_bhs_r2t *bhsr2t; 2591 struct cfiscsi_data_wait *cdw; 2592 struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; | 2510 2511 KASSERT(buffer_offset + response->ip_data_len <= expected_len, 2512 ("buffer_offset %zd + ip_data_len %zd > expected_len %zd", 2513 buffer_offset, response->ip_data_len, expected_len)); 2514 if (buffer_offset + response->ip_data_len == expected_len) { 2515 /* 2516 * Already have the amount of data the initiator wanted. 2517 */ --- 69 unchanged lines hidden (view full) --- 2587cfiscsi_datamove_out(union ctl_io *io) 2588{ 2589 struct cfiscsi_session *cs; 2590 struct icl_pdu *request, *response; 2591 const struct iscsi_bhs_scsi_command *bhssc; 2592 struct iscsi_bhs_r2t *bhsr2t; 2593 struct cfiscsi_data_wait *cdw; 2594 struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; |
2593 uint32_t expected_len, r2t_off, r2t_len; | 2595 uint32_t expected_len, datamove_len, r2t_off, r2t_len; |
2594 uint32_t target_transfer_tag; 2595 bool done; 2596 2597 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2598 cs = PDU_SESSION(request); 2599 2600 bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs; 2601 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 2602 ISCSI_BHS_OPCODE_SCSI_COMMAND, 2603 ("bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND")); 2604 2605 /* 2606 * We need to record it so that we can properly report 2607 * underflow/underflow. 2608 */ 2609 PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len; 2610 2611 /* | 2596 uint32_t target_transfer_tag; 2597 bool done; 2598 2599 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2600 cs = PDU_SESSION(request); 2601 2602 bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs; 2603 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 2604 ISCSI_BHS_OPCODE_SCSI_COMMAND, 2605 ("bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND")); 2606 2607 /* 2608 * We need to record it so that we can properly report 2609 * underflow/underflow. 2610 */ 2611 PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len; 2612 2613 /* |
2612 * Report write underflow as error since CTL and backends don't 2613 * really support it, and SCSI does not tell how to do it right. | 2614 * Complete write underflow. Not a single byte to read. Return. |
2614 */ 2615 expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length); | 2615 */ 2616 expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length); |
2616 if (io->scsiio.kern_rel_offset + io->scsiio.kern_data_len > 2617 expected_len) { 2618 io->scsiio.io_hdr.port_status = 43; | 2617 if (io->scsiio.kern_rel_offset >= expected_len) { |
2619 io->scsiio.be_move_done(io); 2620 return; 2621 } | 2618 io->scsiio.be_move_done(io); 2619 return; 2620 } |
2621 datamove_len = MIN(io->scsiio.kern_data_len, 2622 expected_len - io->scsiio.kern_rel_offset); |
|
2622 2623 target_transfer_tag = 2624 atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1); 2625 cdw = cfiscsi_data_wait_new(cs, io, bhssc->bhssc_initiator_task_tag, 2626 &target_transfer_tag); 2627 if (cdw == NULL) { 2628 CFISCSI_SESSION_WARN(cs, "failed to " 2629 "allocate memory; dropping connection"); --- 6 unchanged lines hidden (view full) --- 2636 CFISCSI_SESSION_DEBUG(cs, "expecting Data-Out with initiator " 2637 "task tag 0x%x, target transfer tag 0x%x", 2638 bhssc->bhssc_initiator_task_tag, target_transfer_tag); 2639#endif 2640 2641 cdw->cdw_ctl_io = io; 2642 cdw->cdw_target_transfer_tag = target_transfer_tag; 2643 cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag; | 2623 2624 target_transfer_tag = 2625 atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1); 2626 cdw = cfiscsi_data_wait_new(cs, io, bhssc->bhssc_initiator_task_tag, 2627 &target_transfer_tag); 2628 if (cdw == NULL) { 2629 CFISCSI_SESSION_WARN(cs, "failed to " 2630 "allocate memory; dropping connection"); --- 6 unchanged lines hidden (view full) --- 2637 CFISCSI_SESSION_DEBUG(cs, "expecting Data-Out with initiator " 2638 "task tag 0x%x, target transfer tag 0x%x", 2639 bhssc->bhssc_initiator_task_tag, target_transfer_tag); 2640#endif 2641 2642 cdw->cdw_ctl_io = io; 2643 cdw->cdw_target_transfer_tag = target_transfer_tag; 2644 cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag; |
2644 cdw->cdw_r2t_end = io->scsiio.kern_data_len; | 2645 cdw->cdw_r2t_end = datamove_len; |
2645 cdw->cdw_datasn = 0; 2646 2647 /* Set initial data pointer for the CDW respecting ext_data_filled. */ 2648 if (io->scsiio.kern_sg_entries > 0) { 2649 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 2650 } else { 2651 ctl_sglist = &ctl_sg_entry; 2652 ctl_sglist->addr = io->scsiio.kern_data_ptr; | 2646 cdw->cdw_datasn = 0; 2647 2648 /* Set initial data pointer for the CDW respecting ext_data_filled. */ 2649 if (io->scsiio.kern_sg_entries > 0) { 2650 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 2651 } else { 2652 ctl_sglist = &ctl_sg_entry; 2653 ctl_sglist->addr = io->scsiio.kern_data_ptr; |
2653 ctl_sglist->len = io->scsiio.kern_data_len; | 2654 ctl_sglist->len = datamove_len; |
2654 } 2655 cdw->cdw_sg_index = 0; 2656 cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr; 2657 cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len; 2658 r2t_off = io->scsiio.ext_data_filled; 2659 while (r2t_off > 0) { 2660 if (r2t_off >= cdw->cdw_sg_len) { 2661 r2t_off -= cdw->cdw_sg_len; --- 14 unchanged lines hidden (view full) --- 2676 if (done) { 2677 cfiscsi_data_wait_free(cs, cdw); 2678 io->scsiio.be_move_done(io); 2679 return; 2680 } 2681 } 2682 2683 r2t_off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled; | 2655 } 2656 cdw->cdw_sg_index = 0; 2657 cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr; 2658 cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len; 2659 r2t_off = io->scsiio.ext_data_filled; 2660 while (r2t_off > 0) { 2661 if (r2t_off >= cdw->cdw_sg_len) { 2662 r2t_off -= cdw->cdw_sg_len; --- 14 unchanged lines hidden (view full) --- 2677 if (done) { 2678 cfiscsi_data_wait_free(cs, cdw); 2679 io->scsiio.be_move_done(io); 2680 return; 2681 } 2682 } 2683 2684 r2t_off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled; |
2684 r2t_len = MIN(io->scsiio.kern_data_len - io->scsiio.ext_data_filled, | 2685 r2t_len = MIN(datamove_len - io->scsiio.ext_data_filled, |
2685 cs->cs_max_burst_length); 2686 cdw->cdw_r2t_end = io->scsiio.ext_data_filled + r2t_len; 2687 2688 CFISCSI_SESSION_LOCK(cs); 2689 TAILQ_INSERT_TAIL(&cs->cs_waiting_for_data_out, cdw, cdw_next); 2690 CFISCSI_SESSION_UNLOCK(cs); 2691 2692 /* --- 278 unchanged lines hidden --- | 2686 cs->cs_max_burst_length); 2687 cdw->cdw_r2t_end = io->scsiio.ext_data_filled + r2t_len; 2688 2689 CFISCSI_SESSION_LOCK(cs); 2690 TAILQ_INSERT_TAIL(&cs->cs_waiting_for_data_out, cdw, cdw_next); 2691 CFISCSI_SESSION_UNLOCK(cs); 2692 2693 /* --- 278 unchanged lines hidden --- |