Add support for WRITE_ATOMIC_16
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
@@ -849,6 +849,11 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
|||||||
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
|
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
|
||||||
iscsi_command_cb cb, void *private_data);
|
iscsi_command_cb cb, void *private_data);
|
||||||
EXTERN struct scsi_task *
|
EXTERN struct scsi_task *
|
||||||
|
iscsi_writeatomic16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
int wrprotect, int dpo, int fua, int group_number,
|
||||||
|
iscsi_command_cb cb, void *private_data);
|
||||||
|
EXTERN struct scsi_task *
|
||||||
iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
unsigned char *data, uint32_t datalen, int blocksize,
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
|
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
|
||||||
@@ -1041,6 +1046,11 @@ iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
|||||||
unsigned char *data, uint32_t datalen, int blocksize,
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||||
|
|
||||||
|
EXTERN struct scsi_task *
|
||||||
|
iscsi_writeatomic16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
int wrprotect, int dpo, int fua, int group_number);
|
||||||
|
|
||||||
EXTERN struct scsi_task *
|
EXTERN struct scsi_task *
|
||||||
iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
unsigned char *data, uint32_t datalen, int blocksize,
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ enum scsi_opcode {
|
|||||||
SCSI_OPCODE_PREFETCH16 = 0x90,
|
SCSI_OPCODE_PREFETCH16 = 0x90,
|
||||||
SCSI_OPCODE_SYNCHRONIZECACHE16 = 0x91,
|
SCSI_OPCODE_SYNCHRONIZECACHE16 = 0x91,
|
||||||
SCSI_OPCODE_WRITE_SAME16 = 0x93,
|
SCSI_OPCODE_WRITE_SAME16 = 0x93,
|
||||||
|
SCSI_OPCODE_WRITE_ATOMIC16 = 0x9C,
|
||||||
SCSI_OPCODE_SERVICE_ACTION_IN = 0x9E,
|
SCSI_OPCODE_SERVICE_ACTION_IN = 0x9E,
|
||||||
SCSI_OPCODE_REPORTLUNS = 0xA0,
|
SCSI_OPCODE_REPORTLUNS = 0xA0,
|
||||||
SCSI_OPCODE_MAINTENANCE_IN = 0xA3,
|
SCSI_OPCODE_MAINTENANCE_IN = 0xA3,
|
||||||
@@ -1065,6 +1066,17 @@ struct scsi_write16_cdb {
|
|||||||
uint8_t control;
|
uint8_t control;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct scsi_writeatomic16_cdb {
|
||||||
|
enum scsi_opcode opcode;
|
||||||
|
uint8_t wrprotect;
|
||||||
|
uint8_t dpo;
|
||||||
|
uint8_t fua;
|
||||||
|
uint32_t lba;
|
||||||
|
uint16_t transfer_length;
|
||||||
|
uint8_t group;
|
||||||
|
uint8_t control;
|
||||||
|
};
|
||||||
|
|
||||||
EXTERN int scsi_datain_getfullsize(struct scsi_task *task);
|
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);
|
||||||
@@ -1096,6 +1108,7 @@ EXTERN struct scsi_task *scsi_cdb_verify16(uint64_t lba, uint32_t xferlen, int v
|
|||||||
EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||||
EXTERN struct scsi_task *scsi_cdb_write12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
EXTERN struct scsi_task *scsi_cdb_write12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||||
EXTERN struct scsi_task *scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
EXTERN struct scsi_task *scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||||
|
EXTERN struct scsi_task *scsi_cdb_writeatomic16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int group_number);
|
||||||
EXTERN struct scsi_task *scsi_cdb_writesame10(int wrprotect, int anchor, int unmap, uint32_t lba, int group, uint16_t num_blocks, uint32_t datalen);
|
EXTERN struct scsi_task *scsi_cdb_writesame10(int wrprotect, int anchor, int unmap, uint32_t lba, int group, uint16_t num_blocks, uint32_t datalen);
|
||||||
EXTERN struct scsi_task *scsi_cdb_writesame16(int wrprotect, int anchor, int unmap, uint64_t lba, int group, uint32_t num_blocks, uint32_t datalen);
|
EXTERN struct scsi_task *scsi_cdb_writesame16(int wrprotect, int anchor, int unmap, uint64_t lba, int group, uint32_t num_blocks, uint32_t datalen);
|
||||||
EXTERN struct scsi_task *scsi_cdb_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
EXTERN struct scsi_task *scsi_cdb_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||||
|
|||||||
@@ -932,6 +932,40 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct scsi_task *
|
||||||
|
iscsi_writeatomic16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
int wrprotect, int dpo, int fua, int group_number,
|
||||||
|
iscsi_command_cb cb, void *private_data)
|
||||||
|
{
|
||||||
|
struct scsi_task *task;
|
||||||
|
struct iscsi_data d;
|
||||||
|
|
||||||
|
if (datalen % blocksize != 0) {
|
||||||
|
iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the "
|
||||||
|
"blocksize:%d.", datalen, blocksize);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
task = scsi_cdb_writeatomic16(lba, datalen, blocksize, wrprotect,
|
||||||
|
dpo, fua, group_number);
|
||||||
|
if (task == NULL) {
|
||||||
|
iscsi_set_error(iscsi, "Out-of-memory: Failed to create "
|
||||||
|
"writeAtomic16 cdb.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
d.data = data;
|
||||||
|
d.size = datalen;
|
||||||
|
|
||||||
|
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
|
||||||
|
&d, private_data) != 0) {
|
||||||
|
scsi_free_scsi_task(task);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
struct scsi_task *
|
struct scsi_task *
|
||||||
iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
unsigned char *data, uint32_t datalen, int blocksize,
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
|||||||
@@ -1810,6 +1810,47 @@ scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, i
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WRITEATOMIC16
|
||||||
|
*/
|
||||||
|
struct scsi_task *
|
||||||
|
scsi_cdb_writeatomic16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int group_number)
|
||||||
|
{
|
||||||
|
struct scsi_task *task;
|
||||||
|
|
||||||
|
task = malloc(sizeof(struct scsi_task));
|
||||||
|
if (task == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(task, 0, sizeof(struct scsi_task));
|
||||||
|
task->cdb[0] = SCSI_OPCODE_WRITE_ATOMIC16;
|
||||||
|
|
||||||
|
task->cdb[1] |= ((wrprotect & 0x07) << 5);
|
||||||
|
if (dpo) {
|
||||||
|
task->cdb[1] |= 0x10;
|
||||||
|
}
|
||||||
|
if (fua) {
|
||||||
|
task->cdb[1] |= 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
scsi_set_uint32(&task->cdb[2], lba >> 32);
|
||||||
|
scsi_set_uint32(&task->cdb[6], lba & 0xffffffff);
|
||||||
|
scsi_set_uint16(&task->cdb[12], xferlen / blocksize);
|
||||||
|
|
||||||
|
task->cdb[14] |= (group_number & 0x1f);
|
||||||
|
|
||||||
|
task->cdb_size = 16;
|
||||||
|
if (xferlen != 0) {
|
||||||
|
task->xfer_dir = SCSI_XFER_WRITE;
|
||||||
|
} else {
|
||||||
|
task->xfer_dir = SCSI_XFER_NONE;
|
||||||
|
}
|
||||||
|
task->expxferlen = xferlen;
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ORWRITE
|
* ORWRITE
|
||||||
*/
|
*/
|
||||||
@@ -3624,6 +3665,28 @@ scsi_write16_cdb_unmarshall(struct scsi_task *task)
|
|||||||
return write16;
|
return write16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct scsi_writeatomic16_cdb *
|
||||||
|
scsi_writeatomic16_cdb_unmarshall(struct scsi_task *task)
|
||||||
|
{
|
||||||
|
struct scsi_writeatomic16_cdb *writeatomic16;
|
||||||
|
|
||||||
|
writeatomic16 = scsi_malloc(task, sizeof(struct scsi_writeatomic16_cdb));
|
||||||
|
if (writeatomic16 == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeatomic16->opcode = SCSI_OPCODE_WRITE_ATOMIC16;
|
||||||
|
writeatomic16->wrprotect = (task->cdb[1] >> 5) & 0x7;
|
||||||
|
writeatomic16->dpo = !!(task->cdb[1] & 0x10);
|
||||||
|
writeatomic16->fua = !!(task->cdb[1] & 0x08);
|
||||||
|
writeatomic16->lba = scsi_get_uint64(&task->cdb[2]);
|
||||||
|
writeatomic16->transfer_length = scsi_get_uint16(&task->cdb[12]);
|
||||||
|
writeatomic16->group = task->cdb[14] & 0x1f;
|
||||||
|
writeatomic16->control = task->cdb[15];
|
||||||
|
|
||||||
|
return writeatomic16;
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode)
|
scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode)
|
||||||
{
|
{
|
||||||
@@ -3652,6 +3715,8 @@ scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode)
|
|||||||
return scsi_write12_cdb_unmarshall(task);
|
return scsi_write12_cdb_unmarshall(task);
|
||||||
case SCSI_OPCODE_WRITE16:
|
case SCSI_OPCODE_WRITE16:
|
||||||
return scsi_write16_cdb_unmarshall(task);
|
return scsi_write16_cdb_unmarshall(task);
|
||||||
|
case SCSI_OPCODE_WRITE_ATOMIC16:
|
||||||
|
return scsi_writeatomic16_cdb_unmarshall(task);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
23
lib/sync.c
23
lib/sync.c
@@ -826,6 +826,29 @@ iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
|||||||
return state.task;
|
return state.task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct scsi_task *
|
||||||
|
iscsi_writeatomic16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
int wrprotect, int dpo, int fua, int group_number)
|
||||||
|
{
|
||||||
|
struct iscsi_sync_state state;
|
||||||
|
|
||||||
|
memset(&state, 0, sizeof(state));
|
||||||
|
|
||||||
|
if (iscsi_writeatomic16_task(iscsi, lun, lba,
|
||||||
|
data, datalen, blocksize, wrprotect,
|
||||||
|
dpo, fua, group_number,
|
||||||
|
scsi_sync_cb, &state) == NULL) {
|
||||||
|
iscsi_set_error(iscsi,
|
||||||
|
"Failed to send WriteAtomic16 command");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_loop(iscsi, &state);
|
||||||
|
|
||||||
|
return state.task;
|
||||||
|
}
|
||||||
|
|
||||||
struct scsi_task *
|
struct scsi_task *
|
||||||
iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
|
||||||
unsigned char *data, uint32_t datalen, int blocksize,
|
unsigned char *data, uint32_t datalen, int blocksize,
|
||||||
|
|||||||
Reference in New Issue
Block a user