Merge branch 'zero_copy_write-3' into resolve-conflicts
Conflicts: lib/iscsi-command.c lib/pdu.c lib/socket.c
This commit is contained in:
@@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* This is the host/port we connect to.*/
|
/* 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)
|
#if defined(WIN32)
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@@ -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;
|
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);
|
exit(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *private_data _U_)
|
||||||
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;
|
struct scsi_task *task = command_data;
|
||||||
int i;
|
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) {
|
if (status == SCSI_STATUS_CHECK_CONDITION) {
|
||||||
printf("Read10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq);
|
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);
|
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++) {
|
for (i=0;i<512;i++) {
|
||||||
printf("%02x ", small_buffer[i]);
|
printf("%02x ", small_buffer[i]);
|
||||||
if (i%16==15)
|
if (i%16==15)
|
||||||
@@ -142,7 +187,9 @@ void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("...\n");
|
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("Finished, wont try to write data since that will likely destroy your LUN :-(\n");
|
||||||
printf("Send NOP-OUT\n");
|
printf("Send NOP-OUT\n");
|
||||||
if (iscsi_nop_out_async(iscsi, nop_out_cb, (unsigned char *)"Ping!", 6, private_data) != 0) {
|
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);
|
scsi_free_scsi_task(task);
|
||||||
exit(10);
|
exit(10);
|
||||||
}
|
}
|
||||||
// printf("write the block back\n");
|
#else
|
||||||
// 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("write the block normally\n");
|
||||||
// printf("failed to send write10 command\n");
|
for (i = 0;i < 512; i++) {
|
||||||
// scsi_free_scsi_task(task);
|
wb[i] = i & 0xff;
|
||||||
// exit(10);
|
}
|
||||||
// }
|
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);
|
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)
|
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
|
* of the data. One in libiscsi and one in the application
|
||||||
* callback.
|
* callback.
|
||||||
*/
|
*/
|
||||||
scsi_task_add_data_in_buffer(task, 128, &small_buffer[0]);
|
scsi_task_add_data_in_buffer(task, 7, &small_buffer[0]);
|
||||||
scsi_task_add_data_in_buffer(task, 512-128, &small_buffer[128]);
|
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)
|
void readcapacity10_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
|
||||||
|
|||||||
@@ -218,10 +218,12 @@ struct iscsi_pdu {
|
|||||||
void *private_data;
|
void *private_data;
|
||||||
|
|
||||||
int written;
|
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;
|
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,
|
struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi,
|
||||||
enum iscsi_opcode opcode,
|
enum iscsi_opcode opcode,
|
||||||
enum iscsi_opcode response_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,
|
struct iscsi_pdu *iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi,
|
||||||
enum iscsi_opcode opcode,
|
enum iscsi_opcode opcode,
|
||||||
enum iscsi_opcode response_opcode,
|
enum iscsi_opcode response_opcode,
|
||||||
uint32_t itt,
|
uint32_t itt,
|
||||||
uint32_t flags);
|
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_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_pduflags(struct iscsi_pdu *pdu, unsigned char flags);
|
||||||
void iscsi_pdu_set_immediate(struct iscsi_pdu *pdu);
|
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)));
|
...) __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 *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_malloc(struct iscsi_context *iscsi, size_t size);
|
||||||
inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size);
|
inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size);
|
||||||
|
|||||||
@@ -537,7 +537,6 @@ iscsi_task_mgmt_target_cold_reset_async(struct iscsi_context *iscsi,
|
|||||||
|
|
||||||
struct iscsi_data {
|
struct iscsi_data {
|
||||||
int size;
|
int size;
|
||||||
size_t alloc_size;
|
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -929,25 +928,33 @@ iscsi_report_supported_opcodes_sync(struct iscsi_context *iscsi, int lun,
|
|||||||
int return_timeouts, int maxsize);
|
int return_timeouts, int maxsize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is used when the application wants to specify its own buffers to read the data
|
* These functions are used when the application wants to specify its own buffers to read the data
|
||||||
* from the DATA-IN PDUs into.
|
* from the DATA-IN PDUs into, or write the data to DATA-OUT PDUs from.
|
||||||
* The main use is for SCSI read operations to have them write directly into the application buffers to
|
* The main use is for SCSI READ10/12/16 WRITE10/12/16 operations to have them read/write directly from
|
||||||
* avoid the two copies that would occur otherwise.
|
* the applications buffer, avoiding coying the data.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* This also supports reading into a vector of buffers by calling this function multiple times.
|
* 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.
|
* 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)
|
* 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, first_buffer, 512
|
||||||
* scsi_task_add_data_in_buffer(task, second_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.size will be 0 and
|
||||||
* task->datain.data will be NULL
|
* 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_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);
|
EXTERN int scsi_task_add_data_out_buffer(struct scsi_task *task, int len, unsigned char *buf);
|
||||||
|
|||||||
@@ -205,10 +205,10 @@ struct scsi_iovec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct scsi_iovector {
|
struct scsi_iovector {
|
||||||
struct scsi_iovec *iov;
|
struct scsi_iovec *iov;
|
||||||
int niov;
|
int niov;
|
||||||
int nalloc;
|
int nalloc;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
int consumed;
|
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_datain_unmarshall(struct scsi_task *task);
|
||||||
EXTERN void *scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode);
|
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_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_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);
|
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);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ iscsi_scsi_response_cb(struct iscsi_context *iscsi, int status,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
|
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) {
|
while (tot_len > 0) {
|
||||||
uint32_t len = tot_len;
|
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;
|
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,
|
ISCSI_PDU_NO_PDU,
|
||||||
cmd_pdu->itt,
|
cmd_pdu->itt,
|
||||||
ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK,
|
ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK);
|
||||||
len);
|
|
||||||
if (pdu == NULL) {
|
if (pdu == NULL) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate "
|
iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate "
|
||||||
"scsi data out pdu.");
|
"scsi data out pdu.");
|
||||||
@@ -82,6 +81,7 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
pdu->scsi_cbdata.task = cmd_pdu->scsi_cbdata.task;
|
||||||
|
|
||||||
if (tot_len == len) {
|
if (tot_len == len) {
|
||||||
flags = ISCSI_PDU_SCSI_FINAL;
|
flags = ISCSI_PDU_SCSI_FINAL;
|
||||||
@@ -107,18 +107,11 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
|
|||||||
/* buffer offset */
|
/* buffer offset */
|
||||||
iscsi_pdu_set_bufferoffset(pdu, offset);
|
iscsi_pdu_set_bufferoffset(pdu, offset);
|
||||||
|
|
||||||
if (iscsi_pdu_add_data(iscsi, pdu, cmd_pdu->nidata.data + offset, len)
|
pdu->out_offset = offset;
|
||||||
!= 0) {
|
pdu->out_len = len;
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: Failed to "
|
|
||||||
"add outdata to the pdu.");
|
/* update data segment length */
|
||||||
SLIST_REMOVE(&iscsi->outqueue, cmd_pdu);
|
scsi_set_uint32(&pdu->outdata.data[4], pdu->out_len);
|
||||||
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->callback = cmd_pdu->callback;
|
pdu->callback = cmd_pdu->callback;
|
||||||
pdu->private_data = cmd_pdu->private_data;
|
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;
|
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
|
int
|
||||||
iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
|
iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
|
||||||
struct scsi_task *task, iscsi_command_cb cb,
|
struct scsi_task *task, iscsi_command_cb cb,
|
||||||
struct iscsi_data *d, void *private_data)
|
struct iscsi_data *d, void *private_data)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
struct iscsi_scsi_cbdata *scsi_cbdata;
|
|
||||||
struct iscsi_data data;
|
|
||||||
uint32_t offset = 0;
|
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
data.data = (d != NULL) ? d->data : NULL;
|
|
||||||
data.size = (d != NULL) ? d->size : 0;
|
|
||||||
|
|
||||||
if (iscsi->session_type != ISCSI_SESSION_NORMAL) {
|
if (iscsi->session_type != ISCSI_SESSION_NORMAL) {
|
||||||
iscsi_set_error(iscsi, "Trying to send command on "
|
iscsi_set_error(iscsi, "Trying to send command on "
|
||||||
"discovery session.");
|
"discovery session.");
|
||||||
@@ -168,21 +158,34 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdu = iscsi_allocate_pdu_size(iscsi, ISCSI_PDU_SCSI_REQUEST,
|
/* Convert old-style callers to the new 'iovector assigned to the task structure'
|
||||||
ISCSI_PDU_SCSI_RESPONSE, data.size);
|
* 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) {
|
if (pdu == NULL) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate "
|
iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate "
|
||||||
"scsi pdu.");
|
"scsi pdu.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_cbdata = &pdu->scsi_cbdata;
|
pdu->scsi_cbdata.task = task;
|
||||||
|
pdu->scsi_cbdata.callback = cb;
|
||||||
|
pdu->scsi_cbdata.private_data = private_data;
|
||||||
|
|
||||||
scsi_cbdata->task = task;
|
scsi_set_task_private_ptr(task, &pdu->scsi_cbdata);
|
||||||
scsi_cbdata->callback = cb;
|
|
||||||
scsi_cbdata->private_data = private_data;
|
|
||||||
|
|
||||||
scsi_set_task_private_ptr(task, scsi_cbdata);
|
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
flags = ISCSI_PDU_SCSI_FINAL|ISCSI_PDU_SCSI_ATTR_SIMPLE;
|
flags = ISCSI_PDU_SCSI_FINAL|ISCSI_PDU_SCSI_ATTR_SIMPLE;
|
||||||
@@ -194,51 +197,21 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
|
|||||||
break;
|
break;
|
||||||
case SCSI_XFER_WRITE:
|
case SCSI_XFER_WRITE:
|
||||||
flags |= ISCSI_PDU_SCSI_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 ? */
|
/* Are we allowed to send immediate data ? */
|
||||||
if (iscsi->use_immediate_data == ISCSI_IMMEDIATE_DATA_YES) {
|
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) {
|
if (len > iscsi->first_burst_length) {
|
||||||
len = iscsi->first_burst_length;
|
len = iscsi->first_burst_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscsi_pdu_add_data(iscsi, pdu, data.data, len)
|
pdu->out_offset = 0;
|
||||||
!= 0) {
|
pdu->out_len = len;
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: Failed to "
|
|
||||||
"add outdata to the pdu.");
|
|
||||||
iscsi_free_pdu(iscsi, pdu);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
offset = len;
|
|
||||||
|
|
||||||
if (len == (uint32_t)data.size) {
|
/* update data segment length */
|
||||||
/* We managed to send it all as immediate data, so there is no non-immediate data left */
|
scsi_set_uint32(&pdu->outdata.data[4], pdu->out_len);
|
||||||
pdu->nidata.data = NULL;
|
} else if (iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO) {
|
||||||
pdu->nidata.size = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdu->nidata.size > 0 && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO) {
|
|
||||||
/* We have more data to send, and we are allowed to send
|
/* We have more data to send, and we are allowed to send
|
||||||
* unsolicited data, so dont flag this PDU as final.
|
* 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);
|
iscsi_pdu_set_cdb(pdu, task);
|
||||||
|
|
||||||
pdu->callback = iscsi_scsi_response_cb;
|
pdu->callback = iscsi_scsi_response_cb;
|
||||||
pdu->private_data = scsi_cbdata;
|
pdu->private_data = &pdu->scsi_cbdata;
|
||||||
|
|
||||||
if (iscsi_queue_pdu(iscsi, pdu) != 0) {
|
if (iscsi_queue_pdu(iscsi, pdu) != 0) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
|
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 ? */
|
/* 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) {
|
if (pdu->out_len != 0 && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO && iscsi->use_immediate_data == ISCSI_IMMEDIATE_DATA_NO) {
|
||||||
uint32_t len = pdu->nidata.size - offset;
|
uint32_t len = task->expxferlen - pdu->out_len;
|
||||||
|
|
||||||
if (len > iscsi->first_burst_length) {
|
if (len > iscsi->first_burst_length) {
|
||||||
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 */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
||||||
struct iscsi_in_pdu *in)
|
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 */
|
/* Dont add to reassembly buffer if we already have a user buffer */
|
||||||
if (scsi_task_get_data_in_buffer(task, 0, NULL) == NULL) {
|
if (scsi_task_get_data_in_buffer(task, 0, NULL) == NULL) {
|
||||||
if (task->expxferlen > dsl && pdu->indata.data == 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);
|
pdu->indata.data = iscsi_malloc(iscsi, task->expxferlen);
|
||||||
if (pdu->indata.data == NULL) {
|
if (pdu->indata.data == NULL) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: failed to allocate pdu indata buffer");
|
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.");
|
"testunitready cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -570,8 +543,8 @@ iscsi_reportluns_task(struct iscsi_context *iscsi, int report_type,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* report luns are always sent to lun 0 */
|
/* report luns are always sent to lun 0 */
|
||||||
if (iscsi_scsi_command_async(iscsi, 0, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, 0, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -592,8 +565,8 @@ iscsi_inquiry_task(struct iscsi_context *iscsi, int lun, int evpd,
|
|||||||
"inquiry cdb.");
|
"inquiry cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -613,8 +586,8 @@ iscsi_readcapacity10_task(struct iscsi_context *iscsi, int lun, int lba,
|
|||||||
"readcapacity10 cdb.");
|
"readcapacity10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -634,8 +607,8 @@ iscsi_readcapacity16_task(struct iscsi_context *iscsi, int lun,
|
|||||||
"readcapacity16 cdb.");
|
"readcapacity16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -656,8 +629,8 @@ iscsi_get_lba_status_task(struct iscsi_context *iscsi, int lun,
|
|||||||
"get-lba-status cdb.");
|
"get-lba-status cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -684,8 +657,8 @@ iscsi_read6_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
|
|||||||
"read6 cdb.");
|
"read6 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -714,8 +687,8 @@ iscsi_read10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
|
|||||||
"read10 cdb.");
|
"read10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -744,8 +717,8 @@ iscsi_read12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
|
|||||||
"read12 cdb.");
|
"read12 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -774,8 +747,8 @@ iscsi_read16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
|||||||
"read16 cdb.");
|
"read16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
||||||
@@ -805,12 +777,21 @@ iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
|
|||||||
"write10 cdb.");
|
"write10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -825,7 +806,6 @@ iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
|
|||||||
iscsi_command_cb cb, void *private_data)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"write12 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"write16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"orwrite cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"compareandwrite cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"writeverify10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"writeverify12 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"writeverify16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = datalen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"verify10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
/* We only transfer data if BYTCHK is true */
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.data = bytchk ? data : NULL;
|
if (iov == NULL) {
|
||||||
outdata.size = bytchk ? datalen : 0;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"verify12 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
/* We only transfer data if BYTCHK is true */
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.data = bytchk ? data : NULL;
|
if (iov == NULL) {
|
||||||
outdata.size = bytchk ? datalen : 0;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
if (datalen % blocksize != 0) {
|
if (datalen % blocksize != 0) {
|
||||||
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
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.");
|
"verify16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
struct scsi_iovec *iov;
|
||||||
|
|
||||||
/* We only transfer data if BYTCHK is true */
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.data = bytchk ? data : NULL;
|
if (iov == NULL) {
|
||||||
outdata.size = bytchk ? datalen : 0;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1180,8 +1238,8 @@ iscsi_modesense6_task(struct iscsi_context *iscsi, int lun, int dbd, int pc,
|
|||||||
"modesense6 cdb.");
|
"modesense6 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1204,8 +1262,8 @@ iscsi_startstopunit_task(struct iscsi_context *iscsi, int lun,
|
|||||||
"startstopunit cdb.");
|
"startstopunit cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1226,8 +1284,8 @@ iscsi_preventallow_task(struct iscsi_context *iscsi, int lun,
|
|||||||
"PreventAllowMediumRemoval cdb.");
|
"PreventAllowMediumRemoval cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1249,8 +1307,8 @@ iscsi_synchronizecache10_task(struct iscsi_context *iscsi, int lun, int lba,
|
|||||||
"synchronizecache10 cdb.");
|
"synchronizecache10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1272,8 +1330,8 @@ iscsi_synchronizecache16_task(struct iscsi_context *iscsi, int lun, uint64_t lba
|
|||||||
"synchronizecache16 cdb.");
|
"synchronizecache16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1294,8 +1352,8 @@ iscsi_prefetch10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
|
|||||||
"prefetch10 cdb.");
|
"prefetch10 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1316,8 +1374,8 @@ iscsi_prefetch16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
|||||||
"prefetch16 cdb.");
|
"prefetch16 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1334,7 +1392,6 @@ iscsi_writesame10_task(struct iscsi_context *iscsi, int lun,
|
|||||||
iscsi_command_cb cb, void *private_data)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
task = scsi_cdb_writesame10(wrprotect, anchor, unmap, pbdata, lbdata, lba, group, num_blocks);
|
task = scsi_cdb_writesame10(wrprotect, anchor, unmap, pbdata, lbdata, lba, group, num_blocks);
|
||||||
if (task == NULL) {
|
if (task == NULL) {
|
||||||
@@ -1343,25 +1400,28 @@ iscsi_writesame10_task(struct iscsi_context *iscsi, int lun,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datalen) {
|
if (data != NULL) {
|
||||||
outdata.data = data;
|
struct scsi_iovec *iov;
|
||||||
outdata.size = datalen;
|
|
||||||
task->expxferlen = datalen;
|
|
||||||
|
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata,
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
private_data) != 0) {
|
if (iov == NULL) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
iov->iov_base = data;
|
||||||
|
iov->iov_len = datalen;
|
||||||
|
scsi_task_set_iov_out(task, iov, 1);
|
||||||
|
|
||||||
|
task->expxferlen = datalen;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
task->expxferlen = 0;
|
task->expxferlen = 0;
|
||||||
task->xfer_dir = SCSI_XFER_NONE;
|
task->xfer_dir = SCSI_XFER_NONE;
|
||||||
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
@@ -1376,7 +1436,6 @@ iscsi_writesame16_task(struct iscsi_context *iscsi, int lun,
|
|||||||
iscsi_command_cb cb, void *private_data)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
|
||||||
|
|
||||||
task = scsi_cdb_writesame16(wrprotect, anchor, unmap, pbdata, lbdata, lba, group, num_blocks);
|
task = scsi_cdb_writesame16(wrprotect, anchor, unmap, pbdata, lbdata, lba, group, num_blocks);
|
||||||
if (task == NULL) {
|
if (task == NULL) {
|
||||||
@@ -1385,25 +1444,29 @@ iscsi_writesame16_task(struct iscsi_context *iscsi, int lun,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datalen) {
|
if (data != NULL) {
|
||||||
outdata.data = data;
|
struct scsi_iovec *iov;
|
||||||
outdata.size = datalen;
|
|
||||||
task->expxferlen = datalen;
|
|
||||||
|
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, &outdata,
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
private_data) != 0) {
|
if (iov == NULL) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
iov->iov_base = data;
|
||||||
|
iov->iov_len = datalen;
|
||||||
|
scsi_task_set_iov_out(task, iov, 1);
|
||||||
|
|
||||||
|
task->expxferlen = datalen;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
task->expxferlen = 0;
|
task->expxferlen = 0;
|
||||||
task->xfer_dir = SCSI_XFER_NONE;
|
task->xfer_dir = SCSI_XFER_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return task;
|
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)
|
iscsi_command_cb cb, void *private_data)
|
||||||
{
|
{
|
||||||
struct scsi_task *task;
|
struct scsi_task *task;
|
||||||
struct iscsi_data outdata;
|
struct scsi_iovec *iov;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int xferlen;
|
int xferlen;
|
||||||
int i;
|
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);
|
scsi_set_uint32(&data[8 + 16 * i + 8], list[0].num);
|
||||||
}
|
}
|
||||||
|
|
||||||
outdata.data = data;
|
iov = scsi_malloc(task, sizeof(struct scsi_iovec));
|
||||||
outdata.size = xferlen;
|
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,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1495,8 +1564,8 @@ iscsi_readtoc_task(struct iscsi_context *iscsi, int lun, int msf,
|
|||||||
"read TOC cdb.");
|
"read TOC cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1516,8 +1585,8 @@ iscsi_reserve6_task(struct iscsi_context *iscsi, int lun,
|
|||||||
"reserve6 cdb.");
|
"reserve6 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1537,8 +1606,8 @@ iscsi_release6_task(struct iscsi_context *iscsi, int lun,
|
|||||||
"release6 cdb.");
|
"release6 cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1559,8 +1628,8 @@ iscsi_report_supported_opcodes_task(struct iscsi_context *iscsi,
|
|||||||
"Maintenance In/Read Supported Op Codes cdb.");
|
"Maintenance In/Read Supported Op Codes cdb.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL,
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
private_data) != 0) {
|
NULL, private_data) != 0) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1627,3 +1696,10 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
|
|||||||
iscsi_free_pdu(iscsi, pdu);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -706,10 +706,10 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
|
|||||||
return -1;
|
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_REQUEST,
|
||||||
ISCSI_PDU_LOGIN_RESPONSE,
|
ISCSI_PDU_LOGIN_RESPONSE,
|
||||||
iscsi->itt, 0, 1024);
|
iscsi->itt, 0);
|
||||||
if (pdu == NULL) {
|
if (pdu == NULL) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
|
iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
|
||||||
"login pdu.");
|
"login pdu.");
|
||||||
|
|||||||
54
lib/pdu.c
54
lib/pdu.c
@@ -61,8 +61,8 @@ iscsi_itt_post_increment(struct iscsi_context *iscsi) {
|
|||||||
|
|
||||||
|
|
||||||
struct iscsi_pdu *
|
struct iscsi_pdu *
|
||||||
iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
|
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, size_t payload_size)
|
enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
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.size = ISCSI_HEADER_SIZE;
|
||||||
pdu->outdata.alloc_size = 64;
|
pdu->outdata.data = iscsi_malloc(iscsi, pdu->outdata.size);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
memset(pdu->outdata.data, 0, ISCSI_HEADER_SIZE);
|
memset(pdu->outdata.data, 0, ISCSI_HEADER_SIZE);
|
||||||
|
|
||||||
if (pdu->outdata.data == NULL) {
|
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;
|
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 *
|
struct iscsi_pdu *
|
||||||
iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
|
iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
|
||||||
enum iscsi_opcode response_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);
|
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
|
void
|
||||||
iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
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;
|
len = data->size + dsize;
|
||||||
|
|
||||||
aligned = len;
|
aligned = len;
|
||||||
if (pdualignment) {
|
if (pdualignment) {
|
||||||
aligned = (aligned+3)&0xfffffffc;
|
aligned = (aligned+3)&0xfffffffc;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t new_alloc_size = data->alloc_size;
|
if (data->size == 0) {
|
||||||
if (new_alloc_size < 64) new_alloc_size=64;
|
data->data = iscsi_malloc(iscsi, aligned);
|
||||||
|
} else {
|
||||||
while (aligned > new_alloc_size) new_alloc_size<<=1;
|
data->data = iscsi_realloc(iscsi, data->data, aligned);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
if (data->alloc_size != new_alloc_size) {
|
|
||||||
data->data = iscsi_realloc(iscsi, data->data, new_alloc_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->data == NULL) {
|
if (data->data == NULL) {
|
||||||
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
|
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
|
||||||
"bytes", (int) len);
|
"bytes", (int) len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->alloc_size = new_alloc_size;
|
|
||||||
memcpy(data->data + data->size, dptr, dsize);
|
memcpy(data->data + data->size, dptr, dsize);
|
||||||
|
data->size += dsize;
|
||||||
|
|
||||||
if (len != aligned) {
|
if (len != aligned) {
|
||||||
/* zero out any padding at the end */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2560,7 +2560,7 @@ scsi_task_set_iov_in(struct scsi_task *task, struct scsi_iovec *iov, int niov)
|
|||||||
|
|
||||||
#define IOVECTOR_INITAL_ALLOC (16)
|
#define IOVECTOR_INITAL_ALLOC (16)
|
||||||
|
|
||||||
int
|
static int
|
||||||
scsi_iovector_add(struct scsi_task *task, struct scsi_iovector *iovector, int len, unsigned char *buf)
|
scsi_iovector_add(struct scsi_task *task, struct scsi_iovector *iovector, int len, unsigned char *buf)
|
||||||
{
|
{
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
|
|||||||
64
lib/socket.c
64
lib/socket.c
@@ -463,13 +463,14 @@ static int
|
|||||||
iscsi_write_to_socket(struct iscsi_context *iscsi)
|
iscsi_write_to_socket(struct iscsi_context *iscsi)
|
||||||
{
|
{
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
|
struct iscsi_pdu *pdu;
|
||||||
|
|
||||||
if (iscsi->fd == -1) {
|
if (iscsi->fd == -1) {
|
||||||
iscsi_set_error(iscsi, "trying to write but not connected");
|
iscsi_set_error(iscsi, "trying to write but not connected");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iscsi->outqueue) {
|
while ((pdu = iscsi->outqueue) != NULL) {
|
||||||
ssize_t total;
|
ssize_t total;
|
||||||
|
|
||||||
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) {
|
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) {
|
||||||
@@ -477,27 +478,58 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
total = iscsi->outqueue->outdata.size;
|
total = pdu->outdata.size;
|
||||||
total = (total + 3) & 0xfffffffc;
|
total = (total + 3) & 0xfffffffc;
|
||||||
|
|
||||||
count = send(iscsi->fd,
|
/* Write header and any immediate data */
|
||||||
iscsi->outqueue->outdata.data
|
if (pdu->written < total) {
|
||||||
+ iscsi->outqueue->written,
|
count = send(iscsi->fd,
|
||||||
total - iscsi->outqueue->written,
|
pdu->outdata.data + pdu->written,
|
||||||
0);
|
total - pdu->written,
|
||||||
if (count == -1) {
|
0);
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (count == -1) {
|
||||||
return 0;
|
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 "
|
pdu->written += count;
|
||||||
"socket :%d", errno);
|
}
|
||||||
return -1;
|
/* if we havent written the full header yet. */
|
||||||
|
if (pdu->written != total) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi->outqueue->written += count;
|
/* Write any iovectors that might have been passed to us */
|
||||||
if (iscsi->outqueue->written == total) {
|
while (pdu->out_len > 0) {
|
||||||
struct iscsi_pdu *pdu = iscsi->outqueue;
|
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);
|
SLIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
|
if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
|
||||||
iscsi_free_pdu(iscsi, pdu);
|
iscsi_free_pdu(iscsi, pdu);
|
||||||
|
|||||||
Reference in New Issue
Block a user