void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { if (pdu == NULL) { iscsi_set_error(iscsi, "trying to free NULL pdu"); return; } free(pdu->outdata.data); pdu->outdata.data = NULL; free(pdu->indata.data); pdu->indata.data = NULL; if (pdu->scsi_cbdata) { iscsi_free_scsi_cbdata(pdu->scsi_cbdata); pdu->scsi_cbdata = NULL; } free(pdu); }
static int iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, struct scsi_task *task, iscsi_command_cb cb, struct iscsi_data *data, void *private_data) { struct iscsi_pdu *pdu; struct iscsi_scsi_cbdata *scsi_cbdata; int flags; if (iscsi == NULL) { printf("trying to send command on NULL context\n"); scsi_free_scsi_task(task); return -1; } if (iscsi->session_type != ISCSI_SESSION_NORMAL) { printf("Trying to send command on discovery session\n"); scsi_free_scsi_task(task); return -2; } if (iscsi->is_loggedin == 0) { printf("Trying to send command while not logged in\n"); scsi_free_scsi_task(task); return -3; } scsi_cbdata = malloc(sizeof(struct iscsi_scsi_cbdata)); if (scsi_cbdata == NULL) { printf("failed to allocate scsi cbdata\n"); scsi_free_scsi_task(task); return -4; } bzero(scsi_cbdata, sizeof(struct iscsi_scsi_cbdata)); scsi_cbdata->task = task; scsi_cbdata->callback = cb; scsi_cbdata->private_data = private_data; pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_REQUEST, ISCSI_PDU_SCSI_RESPONSE); if (pdu == NULL) { printf("Failed to allocate text pdu\n"); iscsi_free_scsi_cbdata(scsi_cbdata); return -5; } pdu->scsi_cbdata = scsi_cbdata; /* flags */ flags = ISCSI_PDU_SCSI_FINAL|ISCSI_PDU_SCSI_ATTR_SIMPLE; switch (task->xfer_dir) { case SCSI_XFER_NONE: break; case SCSI_XFER_READ: flags |= ISCSI_PDU_SCSI_READ; break; case SCSI_XFER_WRITE: flags |= ISCSI_PDU_SCSI_WRITE; if (data == NULL) { printf("DATA-OUT command but data == NULL\n"); iscsi_free_pdu(iscsi, pdu); return -5; } if (data->size != task->expxferlen) { printf("data size:%d is not same as expected data transfer length:%d\n", data->size, task->expxferlen); iscsi_free_pdu(iscsi, pdu); return -7; } if (iscsi_pdu_add_data(iscsi, pdu, data->data, data->size) != 0) { printf("Failed to add outdata to the pdu\n"); iscsi_free_pdu(iscsi, pdu); return -6; } break; } iscsi_pdu_set_pduflags(pdu, flags); /* lun */ iscsi_pdu_set_lun(pdu, lun); /* expxferlen */ iscsi_pdu_set_expxferlen(pdu, task->expxferlen); /* cmdsn */ iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn); pdu->cmdsn = iscsi->cmdsn; iscsi->cmdsn++; /* exp statsn */ iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1); /* cdb */ iscsi_pdu_set_cdb(pdu, task); pdu->callback = iscsi_scsi_response_cb; pdu->private_data = scsi_cbdata; if (iscsi_queue_pdu(iscsi, pdu) != 0) { printf("failed to queue iscsi scsi pdu\n"); iscsi_free_pdu(iscsi, pdu); return -6; } return 0; }