diff --git a/include/iscsi.h b/include/iscsi.h index 9c6ec56..3aac789 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -732,6 +732,15 @@ iscsi_readtoc_task(struct iscsi_context *iscsi, int lun, int msf, int format, int track_session, int maxsize, iscsi_command_cb cb, void *private_data); +EXTERN struct scsi_task * +iscsi_reserve6_task(struct iscsi_context *iscsi, int lun, + iscsi_command_cb cb, void *private_data); + +EXTERN struct scsi_task * +iscsi_release6_task(struct iscsi_context *iscsi, int lun, + iscsi_command_cb cb, void *private_data); + + /* * Sync commands for SCSI */ @@ -889,6 +898,13 @@ EXTERN struct scsi_task * iscsi_readtoc_sync(struct iscsi_context *iscsi, int lun, int msf, int format, int track_session, int maxsize); +EXTERN struct scsi_task * +iscsi_reserve6_sync(struct iscsi_context *iscsi, int lun); + +EXTERN struct scsi_task * +iscsi_release6_sync(struct iscsi_context *iscsi, int lun); + + /* * This function is used when the application wants to specify its own buffers to read the data * from the DATA-IN PDUs into. diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 0483ee1..8ea43f2 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -27,6 +27,8 @@ enum scsi_opcode { SCSI_OPCODE_TESTUNITREADY = 0x00, SCSI_OPCODE_READ6 = 0x08, SCSI_OPCODE_INQUIRY = 0x12, + SCSI_OPCODE_RESERVE6 = 0x16, + SCSI_OPCODE_RELEASE6 = 0x17, SCSI_OPCODE_MODESENSE6 = 0x1a, SCSI_OPCODE_STARTSTOPUNIT = 0x1b, SCSI_OPCODE_PREVENTALLOW = 0x1e, @@ -39,7 +41,7 @@ enum scsi_opcode { SCSI_OPCODE_SYNCHRONIZECACHE10 = 0x35, SCSI_OPCODE_WRITE_SAME10 = 0x41, SCSI_OPCODE_UNMAP = 0x42, - SCSI_OPCODE_READTOC = 0x43, + SCSI_OPCODE_READTOC = 0x43, SCSI_OPCODE_READ16 = 0x88, SCSI_OPCODE_COMPARE_AND_WRITE = 0x89, SCSI_OPCODE_WRITE16 = 0x8A, @@ -362,6 +364,15 @@ struct scsi_reportluns_list { EXTERN struct scsi_task *scsi_reportluns_cdb(int report_type, int alloc_len); +/* + * RESERVE6 + */ +EXTERN struct scsi_task *scsi_cdb_reserve6(void); +/* + * RELEASE6 + */ +EXTERN struct scsi_task *scsi_cdb_release6(void); + /* * READCAPACITY10 */ diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 464b1c2..865a62f 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -48,6 +48,10 @@ iscsi_readcapacity16_sync iscsi_readcapacity16_task iscsi_readtoc_sync iscsi_readtoc_task +iscsi_reserve6_sync +iscsi_reserve6_task +iscsi_release6_sync +iscsi_release6_task iscsi_reconnect iscsi_set_noautoreconnect iscsi_reportluns_sync @@ -124,6 +128,8 @@ scsi_cdb_read6 scsi_cdb_readcapacity10 scsi_cdb_readcapacity16 scsi_cdb_readtoc +scsi_cdb_reserve6 +scsi_cdb_release6 scsi_cdb_serviceactionin16 scsi_cdb_startstopunit scsi_cdb_synchronizecache10 diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index 86373ec..9c6bc3a 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -46,6 +46,10 @@ iscsi_readcapacity16_sync iscsi_readcapacity16_task iscsi_readtoc_sync iscsi_readtoc_task +iscsi_reserve6_sync +iscsi_reserve6_task +iscsi_release6_sync +iscsi_release6_task iscsi_reconnect iscsi_set_noautoreconnect iscsi_reportluns_sync @@ -122,6 +126,8 @@ scsi_cdb_read6 scsi_cdb_readcapacity10 scsi_cdb_readcapacity16 scsi_cdb_readtoc +scsi_cdb_reserve6 +scsi_cdb_release6 scsi_cdb_serviceactionin16 scsi_cdb_startstopunit scsi_cdb_synchronizecache10 diff --git a/lib/scsi-command.c b/lib/scsi-command.c index bef793c..7c6770e 100644 --- a/lib/scsi-command.c +++ b/lib/scsi-command.c @@ -1499,6 +1499,48 @@ iscsi_readtoc_task(struct iscsi_context *iscsi, int lun, int msf, return task; } +struct scsi_task * +iscsi_reserve6_task(struct iscsi_context *iscsi, int lun, + iscsi_command_cb cb, void *private_data) +{ + struct scsi_task *task; + + task = scsi_cdb_reserve6(); + if (task == NULL) { + iscsi_set_error(iscsi, "Out-of-memory: Failed to create " + "reserve6 cdb."); + return NULL; + } + if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, + private_data) != 0) { + scsi_free_scsi_task(task); + return NULL; + } + + return task; +} + +struct scsi_task * +iscsi_release6_task(struct iscsi_context *iscsi, int lun, + iscsi_command_cb cb, void *private_data) +{ + struct scsi_task *task; + + task = scsi_cdb_release6(); + if (task == NULL) { + iscsi_set_error(iscsi, "Out-of-memory: Failed to create " + "release6 cdb."); + return NULL; + } + if (iscsi_scsi_command_async(iscsi, lun, task, cb, NULL, + private_data) != 0) { + scsi_free_scsi_task(task); + return NULL; + } + + return task; +} + struct scsi_task * iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu) { diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index a536177..6846ce7 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -456,6 +456,49 @@ scsi_readtoc_datain_unmarshall(struct scsi_task *task) return list; } +/* + * RESERVE6 + */ +struct scsi_task * +scsi_cdb_reserve6(void) +{ + 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_RESERVE6; + + task->cdb_size = 6; + task->xfer_dir = SCSI_XFER_NONE; + + return task; +} +/* + * RELEASE10 + */ +struct scsi_task * +scsi_cdb_release6(void) +{ + 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_RELEASE6; + + task->cdb_size = 6; + task->xfer_dir = SCSI_XFER_NONE; + + return task; +} + /* * service_action_in unmarshall diff --git a/lib/sync.c b/lib/sync.c index 209ca58..f8903f5 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -840,6 +840,40 @@ iscsi_readtoc_sync(struct iscsi_context *iscsi, int lun, int msf, int format, return state.task; } +struct scsi_task * +iscsi_reserve6_sync(struct iscsi_context *iscsi, int lun) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_reserve6_task(iscsi, lun, scsi_sync_cb, &state) == NULL) { + iscsi_set_error(iscsi, "Failed to send RESERVE6 command"); + return NULL; + } + + event_loop(iscsi, &state); + + return state.task; +} + +struct scsi_task * +iscsi_release6_sync(struct iscsi_context *iscsi, int lun) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_release6_task(iscsi, lun, scsi_sync_cb, &state) == NULL) { + iscsi_set_error(iscsi, "Failed to send RELEASE6 command"); + return NULL; + } + + event_loop(iscsi, &state); + + return state.task; +} + struct scsi_task * iscsi_scsi_command_sync(struct iscsi_context *iscsi, int lun, struct scsi_task *task, struct iscsi_data *data)