void* iscsi_smalloc(struct iscsi_context *iscsi, size_t size) { void *ptr; if (size > iscsi->smalloc_size) return NULL; if (iscsi->smalloc_free > 0) { ptr = iscsi->smalloc_ptrs[--iscsi->smalloc_free]; iscsi->smallocs++; } else { ptr = iscsi_malloc(iscsi, iscsi->smalloc_size); } return ptr; }
int iscsi_init_transport(struct iscsi_context *iscsi, enum iscsi_transport_type transport) { struct tcp_transport *tcp_transport; #ifdef HAVE_LINUX_ISER struct iser_transport *iser_transport; #endif if (iscsi->t) { iscsi_free(iscsi, iscsi->t); iscsi->t = NULL; } iscsi->transport = transport; switch (iscsi->transport) { case TCP_TRANSPORT: tcp_transport = iscsi_malloc(iscsi, sizeof(struct tcp_transport)); if (tcp_transport == NULL) { iscsi_set_error(iscsi, "Couldn't allocate memory for transport\n"); return -1; } iscsi->t = &tcp_transport->t; iscsi_init_tcp_transport(iscsi); break; #ifdef HAVE_LINUX_ISER case ISER_TRANSPORT: iser_transport = iscsi_malloc(iscsi, sizeof(struct iser_transport)); if (iser_transport == NULL) { iscsi_set_error(iscsi, "Couldn't allocate memory for transport\n"); return -1; } iscsi->t = &iser_transport->t; iscsi_init_iser_transport(iscsi); break; #endif default: iscsi_set_error(iscsi, "Unfamiliar transport type"); return -1; } return 0; }
int iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data, unsigned char *dptr, int dsize, int pdualignment) { size_t len, aligned; if (dsize == 0) { iscsi_set_error(iscsi, "Trying to append zero size data to " "iscsi_data"); return -1; } len = data->size + dsize; aligned = len; if (pdualignment) { aligned = (aligned+3)&0xfffffffc; } if (data->size == 0) { if (aligned <= iscsi->smalloc_size) { data->data = iscsi_szmalloc(iscsi, aligned); } else { data->data = iscsi_malloc(iscsi, aligned); } } else { if (aligned > iscsi->smalloc_size) { data->data = iscsi_realloc(iscsi, data->data, aligned); } } if (data->data == NULL) { iscsi_set_error(iscsi, "failed to allocate buffer for %d " "bytes", (int) len); return -1; } memcpy(data->data + data->size, dptr, dsize); data->size += dsize; if (len != aligned) { /* zero out any padding at the end */ memset(data->data + len, 0, aligned - len); } return 0; }
static int iscsi_read_from_socket(struct iscsi_context *iscsi) { struct iscsi_in_pdu *in; ssize_t data_size, count, padding_size; if (iscsi->incoming == NULL) { iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu)); iscsi->incoming->hdr = iscsi_szmalloc(iscsi, ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE); if (iscsi->incoming == NULL) { iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu"); return -1; } } in = iscsi->incoming; /* first we must read the header, including any digests */ if (in->hdr_pos < ISCSI_HEADER_SIZE) { /* try to only read the header, the socket is nonblocking, so * no need to limit the read to what is available in the socket */ count = ISCSI_HEADER_SIZE - in->hdr_pos; count = recv(iscsi->fd, &in->hdr[in->hdr_pos], count, 0); if (count == 0) { return -1; } if (count < 0) { if (errno == EINTR || errno == EAGAIN) { return 0; } iscsi_set_error(iscsi, "read from socket failed, " "errno:%d", errno); return -1; } in->hdr_pos += count; } if (in->hdr_pos < ISCSI_HEADER_SIZE) { /* we don't have the full header yet, so return */ return 0; } padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]); data_size = iscsi_get_pdu_data_size(&in->hdr[0]) + padding_size; if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) { iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size); return -1; } if (data_size != 0) { unsigned char padding_buf[3]; unsigned char *buf = padding_buf; struct scsi_iovector * iovector_in; count = data_size - in->data_pos; /* first try to see if we already have a user buffer */ iovector_in = iscsi_get_scsi_task_iovector_in(iscsi, in); if (iovector_in != NULL && count > padding_size) { uint32_t offset = scsi_get_uint32(&in->hdr[40]); count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count - padding_size, 0); } else { if (iovector_in == NULL) { if (in->data == NULL) { in->data = iscsi_malloc(iscsi, data_size); if (in->data == NULL) { iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size); return -1; } } buf = &in->data[in->data_pos]; } count = recv(iscsi->fd, buf, count, 0); } if (count == 0) { return -1; } if (count < 0) { if (errno == EINTR || errno == EAGAIN) { return 0; } iscsi_set_error(iscsi, "read from socket failed, " "errno:%d %s", errno, iscsi_get_error(iscsi)); return -1; } in->data_pos += count; } if (in->data_pos < data_size) { return 0; } ISCSI_LIST_ADD_END(&iscsi->inqueue, in); iscsi->incoming = NULL; while (iscsi->inqueue != NULL) { struct iscsi_in_pdu *current = iscsi->inqueue; if (iscsi_process_pdu(iscsi, current) != 0) { return -1; } ISCSI_LIST_REMOVE(&iscsi->inqueue, current); iscsi_free_iscsi_in_pdu(iscsi, current); } return 0; }