static void isert_rx_pdu_parse_headers(struct isert_cmnd *isert_pdu) { struct iscsi_cmnd *iscsi_cmnd = &isert_pdu->iscsi; struct isert_buf *isert_buf = &isert_pdu->buf; u8 *addr = isert_buf->addr; struct isert_hdr *isert_hdr = (struct isert_hdr *)addr; struct iscsi_hdr *bhs = (struct iscsi_hdr *)(addr + sizeof(*isert_hdr)); unsigned int data_offset = ISER_HDRS_SZ; unsigned int ahssize; TRACE_ENTRY(); isert_pdu->isert_hdr = isert_hdr; isert_pdu->isert_opcode = isert_hdr->flags & 0xf0; isert_pdu->is_rstag_valid = isert_hdr->flags & ISER_RSV ? 1 : 0; isert_pdu->is_wstag_valid = isert_hdr->flags & ISER_WSV ? 1 : 0; if (isert_pdu->is_rstag_valid) { isert_pdu->rem_read_stag = be32_to_cpu(isert_hdr->read_stag); isert_pdu->rem_read_va = be64_to_cpu(isert_hdr->read_va); } if (isert_pdu->is_wstag_valid) { isert_pdu->rem_write_stag = be32_to_cpu(isert_hdr->write_stag); isert_pdu->rem_write_va = be64_to_cpu(isert_hdr->write_va); } isert_pdu->bhs = bhs; isert_pdu->iscsi_opcode = bhs->opcode & ISCSI_OPCODE_MASK; memcpy(&iscsi_cmnd->pdu.bhs, bhs, sizeof(iscsi_cmnd->pdu.bhs)); iscsi_cmnd_get_length(&iscsi_cmnd->pdu); /* get ahssize and datasize */ ahssize = isert_pdu->iscsi.pdu.ahssize; if (likely(!ahssize)) { isert_pdu->ahs = NULL; } else { isert_pdu->ahs = addr + ISER_HDRS_SZ; data_offset += ahssize; } iscsi_cmnd->pdu.ahs = isert_pdu->ahs; iscsi_cmnd->bufflen = iscsi_cmnd->pdu.datasize; iscsi_cmnd->bufflen = (iscsi_cmnd->bufflen + 3) & ~3; if (iscsi_cmnd->bufflen) { iscsi_cmnd->sg_cnt = isert_pdu->buf.sg_cnt; iscsi_cmnd->sg = isert_pdu->buf.sg; } else { iscsi_cmnd->sg = NULL; } TRACE_EXIT(); }
static ssize_t isert_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct isert_conn_dev *dev = filp->private_data; size_t to_write; if (dev->state == CS_DISCONNECTED) return -EPIPE; to_write = min(count, dev->write_len); if (copy_from_user(dev->write_buf, buf, to_write)) return -EFAULT; dev->write_len -= to_write; dev->write_buf += to_write; switch (dev->state) { case CS_RSP_BHS: if (dev->write_len == 0) { dev->state = CS_RSP_DATA; dev->sg_virt = isert_vmap_sg(dev->pages, dev->login_rsp->sg, dev->login_rsp->sg_cnt); if (!dev->sg_virt) return -ENOMEM; dev->write_buf = dev->sg_virt + ISER_HDRS_SZ; dev->write_len = dev->login_rsp->bufflen - sizeof(dev->login_rsp->pdu.bhs); iscsi_cmnd_get_length(&dev->login_rsp->pdu); } break; case CS_RSP_DATA: break; default: PRINT_ERROR("Invalid state in %s (%d)\n", __func__, dev->state); to_write = 0; } return to_write; }