diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c index a627716..caf2002 100644 --- a/examples/iscsiclient.c +++ b/examples/iscsiclient.c @@ -32,7 +32,7 @@ */ /* This is the host/port we connect to.*/ -#define TARGET "10.1.1.116:3260" +#define TARGET "127.0.0.1:3260" #if defined(WIN32) #include @@ -101,7 +101,7 @@ void nop_out_cb(struct iscsi_context *iscsi, int status, void *command_data, voi } -void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *private_data _U_) +void write10_1_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *private_data _U_) { struct scsi_task *task = command_data; @@ -121,11 +121,56 @@ void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, exit(10); } - -void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) +void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *private_data _U_) { + struct client_state *clnt = (struct client_state *)private_data; struct scsi_task *task = command_data; int i; + static unsigned char wb[512]; + static struct scsi_iovec iov[3]; + + if (status == SCSI_STATUS_CHECK_CONDITION) { + printf("Write10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq); + scsi_free_scsi_task(task); + exit(10); + } + if (status != SCSI_STATUS_GOOD) { + printf("Write10 failed with %s\n", iscsi_get_error(iscsi)); + scsi_free_scsi_task(task); + exit(10); + } + + printf("Write successful :%d\n", status); + scsi_free_scsi_task(task); + + printf("write the block using an iovector\n"); + for (i = 0;i < 512; i++) { + wb[i] = (511 - i) & 0xff; + } + task = iscsi_write10_task(iscsi, clnt->lun, 0, NULL, 512, 512, + 0, 0, 0, 0, 0, + write10_1_cb, private_data); + if (task == NULL) { + printf("failed to send write10 command\n"); + exit(10); + } + /* provide iovectors where to read the data. + */ + iov[0].iov_base = &wb[0]; + iov[0].iov_len = 4; + iov[1].iov_base = &wb[4]; + iov[1].iov_len = 11; + iov[2].iov_base = &wb[15]; + iov[2].iov_len = 512 - 15; + scsi_task_set_iov_out(task, &iov[0], 3); +} + +void read10_1_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) +{ + struct client_state *clnt = (struct client_state *)private_data; + struct scsi_task *task = command_data; + int i; + static unsigned char wb[512]; if (status == SCSI_STATUS_CHECK_CONDITION) { printf("Read10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq); @@ -133,7 +178,7 @@ void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void exit(10); } - printf("READ10 successful. Block content:\n"); + printf("READ10 using scsi_task_set_iov_in() successful. Block content:\n"); for (i=0;i<512;i++) { printf("%02x ", small_buffer[i]); if (i%16==15) @@ -142,7 +187,9 @@ void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void break; } printf("...\n"); + scsi_free_scsi_task(task); +#if 0 printf("Finished, wont try to write data since that will likely destroy your LUN :-(\n"); printf("Send NOP-OUT\n"); if (iscsi_nop_out_async(iscsi, nop_out_cb, (unsigned char *)"Ping!", 6, private_data) != 0) { @@ -150,13 +197,60 @@ void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void scsi_free_scsi_task(task); exit(10); } -// printf("write the block back\n"); -// if (iscsi_write10_async(iscsi, clnt->lun, task->data.datain, task->datain.size, 0, 0, 0, clnt->block_size, write10_cb, private_data) != 0) { -// printf("failed to send write10 command\n"); -// scsi_free_scsi_task(task); -// exit(10); -// } +#else + printf("write the block normally\n"); + for (i = 0;i < 512; i++) { + wb[i] = i & 0xff; + } + task = iscsi_write10_task(iscsi, clnt->lun, 0, wb, 512, 512, + 0, 0, 0, 0, 0, + write10_cb, private_data); + if (task == NULL) { + printf("failed to send write10 command\n"); + exit(10); + } +#endif +} + +void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) +{ + struct client_state *clnt = (struct client_state *)private_data; + struct scsi_task *task = command_data; + int i; + static struct scsi_iovec iov[3]; + + if (status == SCSI_STATUS_CHECK_CONDITION) { + printf("Read10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq); + scsi_free_scsi_task(task); + exit(10); + } + + printf("READ10 using scsi_task_add_data_in_buffer() successful. Block content:\n"); + for (i=0;i<512;i++) { + printf("%02x ", small_buffer[i]); + if (i%16==15) + printf("\n"); + if (i==69) + break; + } + printf("...\n"); scsi_free_scsi_task(task); + + memset(&small_buffer[0], 0, 512); + + if ((task = iscsi_read10_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, 0, 0, 0, 0, 0, read10_1_cb, private_data)) == NULL) { + printf("failed to send read10 command\n"); + exit(10); + } + /* provide iovectors where to read the data. + */ + iov[0].iov_base = &small_buffer[0]; + iov[0].iov_len = 7; + iov[1].iov_base = &small_buffer[7]; + iov[1].iov_len = 8; + iov[2].iov_base = &small_buffer[15]; + iov[2].iov_len = 512 - 15; + scsi_task_set_iov_in(task, &iov[0], 3); } void read6_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) @@ -192,8 +286,9 @@ void read6_cb(struct iscsi_context *iscsi, int status, void *command_data, void * of the data. One in libiscsi and one in the application * callback. */ - scsi_task_add_data_in_buffer(task, 128, &small_buffer[0]); - scsi_task_add_data_in_buffer(task, 512-128, &small_buffer[128]); + scsi_task_add_data_in_buffer(task, 7, &small_buffer[0]); + scsi_task_add_data_in_buffer(task, 8, &small_buffer[7]); + scsi_task_add_data_in_buffer(task, 512-15, &small_buffer[15]); } void readcapacity10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 0ec772e..0e425ad 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -218,10 +218,12 @@ struct iscsi_pdu { void *private_data; int written; - struct iscsi_data outdata; /* Header and Immediate Data */ - struct iscsi_data indata; - struct iscsi_data nidata; /* Non-Immediate Data */ + struct iscsi_data outdata; /* Header for PDU to send */ + uint32_t out_offset; /* Offset into data-out iovector */ + uint32_t out_len; /* Amount of data to sent */ + + struct iscsi_data indata; struct iscsi_scsi_cbdata scsi_cbdata; }; @@ -231,21 +233,11 @@ void iscsi_free_scsi_cbdata(struct iscsi_context *iscsi, struct iscsi_scsi_cbdat struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode, enum iscsi_opcode response_opcode); -struct iscsi_pdu *iscsi_allocate_pdu_size(struct iscsi_context *iscsi, - enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, - size_t payload_size); struct iscsi_pdu *iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode opcode, enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags); -struct iscsi_pdu *iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, - enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, - uint32_t itt, - uint32_t flags, - size_t payload_size); void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); void iscsi_pdu_set_pduflags(struct iscsi_pdu *pdu, unsigned char flags); void iscsi_pdu_set_immediate(struct iscsi_pdu *pdu); @@ -303,7 +295,8 @@ void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, ...) __attribute__((format(printf, 2, 3))); unsigned char *iscsi_get_user_in_buffer(struct iscsi_context *iscsi, struct iscsi_in_pdu *in, uint32_t pos, ssize_t *count); -unsigned char *scsi_task_get_data_in_buffer(struct scsi_task *task, uint32_t pos, ssize_t *count); +unsigned char *iscsi_get_user_out_buffer(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, uint32_t pos, ssize_t *count); + inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size); inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size); diff --git a/include/iscsi.h b/include/iscsi.h index cddd298..827b9de 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -537,7 +537,6 @@ iscsi_task_mgmt_target_cold_reset_async(struct iscsi_context *iscsi, struct iscsi_data { int size; - size_t alloc_size; unsigned char *data; }; @@ -929,25 +928,33 @@ iscsi_report_supported_opcodes_sync(struct iscsi_context *iscsi, int lun, int return_timeouts, int maxsize); /* - * This function is used when the application wants to specify its own buffers to read the data - * from the DATA-IN PDUs into. - * The main use is for SCSI read operations to have them write directly into the application buffers to - * avoid the two copies that would occur otherwise. - * First copy from the individual DATA-IN blobs to linearize the buffer and the second in the callback - * to copy the data from the linearized buffer into the application buffer. + * These functions are used when the application wants to specify its own buffers to read the data + * from the DATA-IN PDUs into, or write the data to DATA-OUT PDUs from. + * The main use is for SCSI READ10/12/16 WRITE10/12/16 operations to have them read/write directly from + * the applications buffer, avoiding coying the data. * * This also supports reading into a vector of buffers by calling this function multiple times. * The individual buffers will be filled in the same order as they were created. * - * Example: + * Example READ10: * task = iscsi_read10_task( ( 2 512byte blocks into two buffers) * scsi_task_add_data_in_buffer(task, first_buffer, 512 * scsi_task_add_data_in_buffer(task, second_buffer, 512 * * - * If you use this function you can not use task->datain in the callback. + * If you use this function you can not use task->datain in the READ callback. * task->datain.size will be 0 and * task->datain.data will be NULL + * + * Example WRITE10: (write 2 blocks) + * static struct scsi_iovec iov[2]; + * + * task = iscsi_write10_task(iscsi, lun, 0, NULL, 512, 512, 0, 0, 0, 0, 0, callback, private_data); + * iov[0].iov_base = first_buffer; + * iov[0].iov_len = 512; + * iov[1].iov_base = second_buffer; + * iov[1].iov_len = 512; + * scsi_task_set_iov_out(task, &iov[0], 2); */ EXTERN int scsi_task_add_data_in_buffer(struct scsi_task *task, int len, unsigned char *buf); EXTERN int scsi_task_add_data_out_buffer(struct scsi_task *task, int len, unsigned char *buf); diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 109694c..beca19d 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -205,10 +205,10 @@ struct scsi_iovec { }; struct scsi_iovector { - struct scsi_iovec *iov; - int niov; - int nalloc; - size_t size; + struct scsi_iovec *iov; + int niov; + int nalloc; + size_t size; size_t offset; int consumed; }; @@ -690,6 +690,9 @@ EXTERN int scsi_datain_getfullsize(struct scsi_task *task); EXTERN void *scsi_datain_unmarshall(struct scsi_task *task); EXTERN void *scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode); +unsigned char *scsi_task_get_data_in_buffer(struct scsi_task *task, uint32_t pos, ssize_t *count); +unsigned char *scsi_task_get_data_out_buffer(struct scsi_task *task, uint32_t pos, ssize_t *count); + EXTERN struct scsi_task *scsi_cdb_read6(uint32_t lba, uint32_t xferlen, int blocksize); EXTERN struct scsi_task *scsi_cdb_read10(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number); EXTERN struct scsi_task *scsi_cdb_read12(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number); diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index d006af7..3f344fe 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -55,7 +55,7 @@ iscsi_scsi_response_cb(struct iscsi_context *iscsi, int status, static int iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, - uint32_t ttt, uint32_t offset, uint32_t tot_len) + uint32_t ttt, uint32_t offset, uint32_t tot_len) { while (tot_len > 0) { uint32_t len = tot_len; @@ -66,11 +66,10 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, len = iscsi->target_max_recv_data_segment_length; } - pdu = iscsi_allocate_pdu_with_itt_flags_size(iscsi, ISCSI_PDU_DATA_OUT, + pdu = iscsi_allocate_pdu_with_itt_flags(iscsi, ISCSI_PDU_DATA_OUT, ISCSI_PDU_NO_PDU, cmd_pdu->itt, - ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK, - len); + ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate " "scsi data out pdu."); @@ -82,6 +81,7 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, return -1; } + pdu->scsi_cbdata.task = cmd_pdu->scsi_cbdata.task; if (tot_len == len) { flags = ISCSI_PDU_SCSI_FINAL; @@ -107,18 +107,11 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, /* buffer offset */ iscsi_pdu_set_bufferoffset(pdu, offset); - if (iscsi_pdu_add_data(iscsi, pdu, cmd_pdu->nidata.data + offset, len) - != 0) { - iscsi_set_error(iscsi, "Out-of-memory: Failed to " - "add outdata to the pdu."); - SLIST_REMOVE(&iscsi->outqueue, cmd_pdu); - SLIST_REMOVE(&iscsi->waitpdu, cmd_pdu); - cmd_pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL, - cmd_pdu->private_data); - iscsi_free_pdu(iscsi, cmd_pdu); - iscsi_free_pdu(iscsi, pdu); - return -1; - } + pdu->out_offset = offset; + pdu->out_len = len; + + /* update data segment length */ + scsi_set_uint32(&pdu->outdata.data[4], pdu->out_len); pdu->callback = cmd_pdu->callback; pdu->private_data = cmd_pdu->private_data; @@ -141,21 +134,18 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, return 0; } +/* Using 'struct iscsi_data *d' for data-out is depreciated. + * Instead the task should have a data-out iovector attached to it. + * See iscsi_write10_task for an example. + */ int iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, - struct scsi_task *task, iscsi_command_cb cb, - struct iscsi_data *d, void *private_data) + struct scsi_task *task, iscsi_command_cb cb, + struct iscsi_data *d, void *private_data) { struct iscsi_pdu *pdu; - struct iscsi_scsi_cbdata *scsi_cbdata; - struct iscsi_data data; - uint32_t offset = 0; - int flags; - data.data = (d != NULL) ? d->data : NULL; - data.size = (d != NULL) ? d->size : 0; - if (iscsi->session_type != ISCSI_SESSION_NORMAL) { iscsi_set_error(iscsi, "Trying to send command on " "discovery session."); @@ -168,22 +158,35 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, return -1; } - pdu = iscsi_allocate_pdu_size(iscsi, ISCSI_PDU_SCSI_REQUEST, - ISCSI_PDU_SCSI_RESPONSE, data.size); + /* Convert old-style callers to the new 'iovector assigned to the task structure' + * model. + */ + if (d != NULL && d->data != NULL) { + struct scsi_iovec *iov; + + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + return -1; + } + iov->iov_base = d->data; + iov->iov_len = d->size; + scsi_task_set_iov_out(task, iov, 1); + } + + pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_REQUEST, + ISCSI_PDU_SCSI_RESPONSE); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate " "scsi pdu."); return -1; } - - scsi_cbdata = &pdu->scsi_cbdata; - - scsi_cbdata->task = task; - scsi_cbdata->callback = cb; - scsi_cbdata->private_data = private_data; - scsi_set_task_private_ptr(task, scsi_cbdata); + pdu->scsi_cbdata.task = task; + pdu->scsi_cbdata.callback = cb; + pdu->scsi_cbdata.private_data = private_data; + scsi_set_task_private_ptr(task, &pdu->scsi_cbdata); + /* flags */ flags = ISCSI_PDU_SCSI_FINAL|ISCSI_PDU_SCSI_ATTR_SIMPLE; switch (task->xfer_dir) { @@ -194,51 +197,21 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, break; case SCSI_XFER_WRITE: flags |= ISCSI_PDU_SCSI_WRITE; - if (data.size == 0) { - iscsi_set_error(iscsi, "DATA-OUT command but data " - "== NULL."); - iscsi_free_pdu(iscsi, pdu); - return -1; - } - if (data.size != task->expxferlen) { - iscsi_set_error(iscsi, "Data size:%d is not same as " - "expected data transfer " - "length:%d.", data.size, - task->expxferlen); - iscsi_free_pdu(iscsi, pdu); - return -1; - } - - /* Assume all data is non-immediate data */ - pdu->nidata.data = data.data; - pdu->nidata.size = data.size; /* Are we allowed to send immediate data ? */ if (iscsi->use_immediate_data == ISCSI_IMMEDIATE_DATA_YES) { - uint32_t len = data.size; + uint32_t len = task->expxferlen; if (len > iscsi->first_burst_length) { len = iscsi->first_burst_length; } - if (iscsi_pdu_add_data(iscsi, pdu, data.data, len) - != 0) { - iscsi_set_error(iscsi, "Out-of-memory: Failed to " - "add outdata to the pdu."); - iscsi_free_pdu(iscsi, pdu); - return -1; - } - offset = len; + pdu->out_offset = 0; + pdu->out_len = len; - if (len == (uint32_t)data.size) { - /* We managed to send it all as immediate data, so there is no non-immediate data left */ - pdu->nidata.data = NULL; - pdu->nidata.size = 0; - - } - } - - if (pdu->nidata.size > 0 && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO) { + /* update data segment length */ + scsi_set_uint32(&pdu->outdata.data[4], pdu->out_len); + } else if (iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO) { /* We have more data to send, and we are allowed to send * unsolicited data, so dont flag this PDU as final. */ @@ -267,7 +240,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, iscsi_pdu_set_cdb(pdu, task); pdu->callback = iscsi_scsi_response_cb; - pdu->private_data = scsi_cbdata; + pdu->private_data = &pdu->scsi_cbdata; if (iscsi_queue_pdu(iscsi, pdu) != 0) { iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi " @@ -277,13 +250,14 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, } /* Can we send some unsolicited data ? */ - if (pdu->nidata.size != 0 && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO && iscsi->use_immediate_data == ISCSI_IMMEDIATE_DATA_NO) { - uint32_t len = pdu->nidata.size - offset; + if (pdu->out_len != 0 && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO && iscsi->use_immediate_data == ISCSI_IMMEDIATE_DATA_NO) { + uint32_t len = task->expxferlen - pdu->out_len; if (len > iscsi->first_burst_length) { len = iscsi->first_burst_length; } - iscsi_send_data_out(iscsi, pdu, 0xffffffff, offset, len); + iscsi_send_data_out(iscsi, pdu, 0xffffffff, + pdu->out_offset, len); } /* remember cmdsn and itt so we can use task management */ @@ -294,7 +268,6 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, return 0; } - int iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, struct iscsi_in_pdu *in) @@ -443,7 +416,7 @@ iscsi_process_scsi_data_in(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, /* Dont add to reassembly buffer if we already have a user buffer */ if (scsi_task_get_data_in_buffer(task, 0, NULL) == NULL) { if (task->expxferlen > dsl && pdu->indata.data == NULL) { - pdu->indata.alloc_size = task->expxferlen; + pdu->indata.size = task->expxferlen; pdu->indata.data = iscsi_malloc(iscsi, task->expxferlen); if (pdu->indata.data == NULL) { iscsi_set_error(iscsi, "Out-of-memory: failed to allocate pdu indata buffer"); @@ -541,8 +514,8 @@ iscsi_testunitready_task(struct iscsi_context *iscsi, int lun, "testunitready cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -570,8 +543,8 @@ iscsi_reportluns_task(struct iscsi_context *iscsi, int report_type, return NULL; } /* report luns are always sent to lun 0 */ - if (iscsi_scsi_command_async(iscsi, 0, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, 0, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -592,8 +565,8 @@ iscsi_inquiry_task(struct iscsi_context *iscsi, int lun, int evpd, "inquiry cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -613,8 +586,8 @@ iscsi_readcapacity10_task(struct iscsi_context *iscsi, int lun, int lba, "readcapacity10 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -634,8 +607,8 @@ iscsi_readcapacity16_task(struct iscsi_context *iscsi, int lun, "readcapacity16 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -656,8 +629,8 @@ iscsi_get_lba_status_task(struct iscsi_context *iscsi, int lun, "get-lba-status cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -684,8 +657,8 @@ iscsi_read6_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "read6 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -714,8 +687,8 @@ iscsi_read10_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "read10 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -744,8 +717,8 @@ iscsi_read12_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "read12 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -774,8 +747,8 @@ iscsi_read16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, "read16 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -790,7 +763,6 @@ iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -805,16 +777,25 @@ iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "write10 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } - + return task; } @@ -825,7 +806,6 @@ iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -840,12 +820,21 @@ iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "write12 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -860,7 +849,6 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -875,12 +863,21 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, "write16 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -895,7 +892,6 @@ iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -910,12 +906,21 @@ iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, "orwrite cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -930,7 +935,6 @@ iscsi_compareandwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -945,12 +949,21 @@ iscsi_compareandwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, "compareandwrite cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -965,7 +978,6 @@ iscsi_writeverify10_task(struct iscsi_context *iscsi, int lun, uint32_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -980,12 +992,21 @@ iscsi_writeverify10_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "writeverify10 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1000,7 +1021,6 @@ iscsi_writeverify12_task(struct iscsi_context *iscsi, int lun, uint32_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -1015,12 +1035,21 @@ iscsi_writeverify12_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "writeverify12 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1035,7 +1064,6 @@ iscsi_writeverify16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -1050,12 +1078,21 @@ iscsi_writeverify16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, "writeverify16 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - outdata.data = data; - outdata.size = datalen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1069,7 +1106,6 @@ iscsi_verify10_task(struct iscsi_context *iscsi, int lun, unsigned char *data, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -1083,13 +1119,21 @@ iscsi_verify10_task(struct iscsi_context *iscsi, int lun, unsigned char *data, "verify10 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - /* We only transfer data if BYTCHK is true */ - outdata.data = bytchk ? data : NULL; - outdata.size = bytchk ? datalen : 0; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1103,7 +1147,6 @@ iscsi_verify12_task(struct iscsi_context *iscsi, int lun, unsigned char *data, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -1117,13 +1160,21 @@ iscsi_verify12_task(struct iscsi_context *iscsi, int lun, unsigned char *data, "verify12 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - /* We only transfer data if BYTCHK is true */ - outdata.data = bytchk ? data : NULL; - outdata.size = bytchk ? datalen : 0; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1137,7 +1188,6 @@ iscsi_verify16_task(struct iscsi_context *iscsi, int lun, unsigned char *data, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; if (datalen % blocksize != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " @@ -1151,13 +1201,21 @@ iscsi_verify16_task(struct iscsi_context *iscsi, int lun, unsigned char *data, "verify16 cdb."); return NULL; } + if (data != NULL) { + struct scsi_iovec *iov; - /* We only transfer data if BYTCHK is true */ - outdata.data = bytchk ? data : NULL; - outdata.size = bytchk ? datalen : 0; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1180,8 +1238,8 @@ iscsi_modesense6_task(struct iscsi_context *iscsi, int lun, int dbd, int pc, "modesense6 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1204,8 +1262,8 @@ iscsi_startstopunit_task(struct iscsi_context *iscsi, int lun, "startstopunit cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1226,8 +1284,8 @@ iscsi_preventallow_task(struct iscsi_context *iscsi, int lun, "PreventAllowMediumRemoval cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1249,8 +1307,8 @@ iscsi_synchronizecache10_task(struct iscsi_context *iscsi, int lun, int lba, "synchronizecache10 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1272,8 +1330,8 @@ iscsi_synchronizecache16_task(struct iscsi_context *iscsi, int lun, uint64_t lba "synchronizecache16 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1294,8 +1352,8 @@ iscsi_prefetch10_task(struct iscsi_context *iscsi, int lun, uint32_t lba, "prefetch10 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1316,8 +1374,8 @@ iscsi_prefetch16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, "prefetch16 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1334,7 +1392,6 @@ iscsi_writesame10_task(struct iscsi_context *iscsi, int lun, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; task = scsi_cdb_writesame10(wrprotect, anchor, unmap, pbdata, lbdata, lba, group, num_blocks); if (task == NULL) { @@ -1343,25 +1400,28 @@ iscsi_writesame10_task(struct iscsi_context *iscsi, int lun, return NULL; } - if (datalen) { - outdata.data = data; - outdata.size = datalen; - task->expxferlen = datalen; + if (data != NULL) { + struct scsi_iovec *iov; - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { scsi_free_scsi_task(task); return NULL; } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + + task->expxferlen = datalen; + } else { task->expxferlen = 0; task->xfer_dir = SCSI_XFER_NONE; - - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { - scsi_free_scsi_task(task); - return NULL; - } + } + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { + scsi_free_scsi_task(task); + return NULL; } return task; @@ -1376,7 +1436,6 @@ iscsi_writesame16_task(struct iscsi_context *iscsi, int lun, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; task = scsi_cdb_writesame16(wrprotect, anchor, unmap, pbdata, lbdata, lba, group, num_blocks); if (task == NULL) { @@ -1385,25 +1444,29 @@ iscsi_writesame16_task(struct iscsi_context *iscsi, int lun, return NULL; } - if (datalen) { - outdata.data = data; - outdata.size = datalen; - task->expxferlen = datalen; + if (data != NULL) { + struct scsi_iovec *iov; - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { scsi_free_scsi_task(task); return NULL; } + iov->iov_base = data; + iov->iov_len = datalen; + scsi_task_set_iov_out(task, iov, 1); + + task->expxferlen = datalen; + } else { task->expxferlen = 0; task->xfer_dir = SCSI_XFER_NONE; + } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { - scsi_free_scsi_task(task); - return NULL; - } + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { + scsi_free_scsi_task(task); + return NULL; } return task; @@ -1415,7 +1478,7 @@ iscsi_unmap_task(struct iscsi_context *iscsi, int lun, int anchor, int group, iscsi_command_cb cb, void *private_data) { struct scsi_task *task; - struct iscsi_data outdata; + struct scsi_iovec *iov; unsigned char *data; int xferlen; int i; @@ -1444,11 +1507,17 @@ iscsi_unmap_task(struct iscsi_context *iscsi, int lun, int anchor, int group, scsi_set_uint32(&data[8 + 16 * i + 8], list[0].num); } - outdata.data = data; - outdata.size = xferlen; + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + scsi_free_scsi_task(task); + return NULL; + } + iov->iov_base = data; + iov->iov_len = xferlen; + scsi_task_set_iov_out(task, iov, 1); - if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1495,8 +1564,8 @@ iscsi_readtoc_task(struct iscsi_context *iscsi, int lun, int msf, "read TOC cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1516,8 +1585,8 @@ iscsi_reserve6_task(struct iscsi_context *iscsi, int lun, "reserve6 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1537,8 +1606,8 @@ iscsi_release6_task(struct iscsi_context *iscsi, int lun, "release6 cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1559,8 +1628,8 @@ iscsi_report_supported_opcodes_task(struct iscsi_context *iscsi, "Maintenance In/Read Supported Op Codes cdb."); return NULL; } - if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, - private_data) != 0) { + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { scsi_free_scsi_task(task); return NULL; } @@ -1627,3 +1696,10 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi) iscsi_free_pdu(iscsi, pdu); } } + +unsigned char * +iscsi_get_user_out_buffer(struct iscsi_context *iscsi _U_, struct iscsi_pdu *pdu, uint32_t pos, ssize_t *count) +{ + return scsi_task_get_data_out_buffer(pdu->scsi_cbdata.task, pos, count); +} + diff --git a/lib/login.c b/lib/login.c index 66e2146..6635629 100644 --- a/lib/login.c +++ b/lib/login.c @@ -706,10 +706,10 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, return -1; } - pdu = iscsi_allocate_pdu_with_itt_flags_size(iscsi, + pdu = iscsi_allocate_pdu_with_itt_flags(iscsi, ISCSI_PDU_LOGIN_REQUEST, ISCSI_PDU_LOGIN_RESPONSE, - iscsi->itt, 0, 1024); + iscsi->itt, 0); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate " "login pdu."); diff --git a/lib/pdu.c b/lib/pdu.c index 25f05a5..b8073c4 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -61,8 +61,8 @@ iscsi_itt_post_increment(struct iscsi_context *iscsi) { struct iscsi_pdu * -iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags, size_t payload_size) +iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode opcode, + enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags) { struct iscsi_pdu *pdu; @@ -73,14 +73,7 @@ iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, enum iscsi_o } pdu->outdata.size = ISCSI_HEADER_SIZE; - pdu->outdata.alloc_size = 64; - - /* payload_size is limited by negotiated max_recv_data_segment_length */ - if (payload_size > iscsi->target_max_recv_data_segment_length) - payload_size = iscsi->target_max_recv_data_segment_length; - - while (pdu->outdata.alloc_size < ISCSI_HEADER_SIZE+payload_size) pdu->outdata.alloc_size<<=1; - pdu->outdata.data = iscsi_malloc(iscsi, pdu->outdata.alloc_size); + pdu->outdata.data = iscsi_malloc(iscsi, pdu->outdata.size); memset(pdu->outdata.data, 0, ISCSI_HEADER_SIZE); if (pdu->outdata.data == NULL) { @@ -108,13 +101,6 @@ iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, enum iscsi_o return pdu; } -struct iscsi_pdu * -iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags) -{ - return iscsi_allocate_pdu_with_itt_flags_size(iscsi, opcode, response_opcode, itt, flags, 0); -} - struct iscsi_pdu * iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode, enum iscsi_opcode response_opcode) @@ -122,15 +108,6 @@ iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode, return iscsi_allocate_pdu_with_itt_flags(iscsi, opcode, response_opcode, iscsi_itt_post_increment(iscsi), 0); } -struct iscsi_pdu * -iscsi_allocate_pdu_size(struct iscsi_context *iscsi, enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, size_t payload_size) -{ - return iscsi_allocate_pdu_with_itt_flags_size(iscsi, opcode, response_opcode, iscsi_itt_post_increment(iscsi), 0, payload_size); -} - - - void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { @@ -162,42 +139,31 @@ iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data, } len = data->size + dsize; + aligned = len; if (pdualignment) { aligned = (aligned+3)&0xfffffffc; } - size_t new_alloc_size = data->alloc_size; - if (new_alloc_size < 64) new_alloc_size=64; - - while (aligned > new_alloc_size) new_alloc_size<<=1; - - if (data->data != NULL && data->alloc_size == 0) data->alloc_size=data->size; - - if (data->alloc_size == 0) { - data->data = iscsi_malloc(iscsi, new_alloc_size); + if (data->size == 0) { + data->data = iscsi_malloc(iscsi, aligned); + } else { + data->data = iscsi_realloc(iscsi, data->data, aligned); } - else - if (data->alloc_size != new_alloc_size) { - data->data = iscsi_realloc(iscsi, data->data, new_alloc_size); - } - if (data->data == NULL) { iscsi_set_error(iscsi, "failed to allocate buffer for %d " "bytes", (int) len); return -1; } - - data->alloc_size = new_alloc_size; + 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); + memset(data->data + len, 0, aligned - len); } - data->size = len; - return 0; } diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 04febce..0f2e5f3 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -2560,7 +2560,7 @@ scsi_task_set_iov_in(struct scsi_task *task, struct scsi_iovec *iov, int niov) #define IOVECTOR_INITAL_ALLOC (16) -int +static int scsi_iovector_add(struct scsi_task *task, struct scsi_iovector *iovector, int len, unsigned char *buf) { if (len < 0) { diff --git a/lib/socket.c b/lib/socket.c index 4b40970..88f1a2a 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -463,13 +463,14 @@ static int iscsi_write_to_socket(struct iscsi_context *iscsi) { ssize_t count; + struct iscsi_pdu *pdu; if (iscsi->fd == -1) { iscsi_set_error(iscsi, "trying to write but not connected"); return -1; } - while (iscsi->outqueue) { + while ((pdu = iscsi->outqueue) != NULL) { ssize_t total; if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) { @@ -477,27 +478,58 @@ iscsi_write_to_socket(struct iscsi_context *iscsi) return 0; } - total = iscsi->outqueue->outdata.size; + total = pdu->outdata.size; total = (total + 3) & 0xfffffffc; - count = send(iscsi->fd, - iscsi->outqueue->outdata.data - + iscsi->outqueue->written, - total - iscsi->outqueue->written, - 0); - if (count == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return 0; + /* Write header and any immediate data */ + if (pdu->written < total) { + count = send(iscsi->fd, + pdu->outdata.data + pdu->written, + total - pdu->written, + 0); + if (count == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + return 0; + } + iscsi_set_error(iscsi, "Error when writing to " + "socket :%d", errno); + return -1; } - iscsi_set_error(iscsi, "Error when writing to " - "socket :%d", errno); - return -1; + pdu->written += count; + } + /* if we havent written the full header yet. */ + if (pdu->written != total) { + return 0; } - iscsi->outqueue->written += count; - if (iscsi->outqueue->written == total) { - struct iscsi_pdu *pdu = iscsi->outqueue; + /* Write any iovectors that might have been passed to us */ + while (pdu->out_len > 0) { + unsigned char *buf; + count = pdu->out_len; + buf = iscsi_get_user_out_buffer(iscsi, pdu, pdu->out_offset, &count); + if (buf == NULL) { + iscsi_set_error(iscsi, "Can't find iovector data for DATA-OUT"); + return -1; + } + + count = send(iscsi->fd, + buf, + count, + 0); + if (count == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + return 0; + } + iscsi_set_error(iscsi, "Error when writing to " + "socket :%d", errno); + return -1; + } + pdu->out_offset += count; + pdu->out_len -= count; + } + + if (pdu->written == total) { SLIST_REMOVE(&iscsi->outqueue, pdu); if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) { iscsi_free_pdu(iscsi, pdu);