From 16da01ed4e3430b57260f9dfcdaad35c2eacbe11 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 17 Jul 2012 18:12:03 +1000 Subject: [PATCH] Add PREVENTALLOWMEDIUMREMOVAL support --- include/iscsi.h | 8 ++++++++ include/scsi-lowlevel.h | 6 ++++++ lib/libiscsi.def | 3 +++ lib/libiscsi.syms | 3 +++ lib/scsi-command.c | 22 ++++++++++++++++++++++ lib/scsi-lowlevel.c | 27 +++++++++++++++++++++++++++ lib/sync.c | 20 ++++++++++++++++++++ 7 files changed, 89 insertions(+) diff --git a/include/iscsi.h b/include/iscsi.h index f980e64..fb55dbc 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -666,6 +666,10 @@ iscsi_startstopunit_task(struct iscsi_context *iscsi, int lun, int no_flush, int loej, int start, iscsi_command_cb cb, void *private_data); EXTERN struct scsi_task * +iscsi_preventallow_task(struct iscsi_context *iscsi, int lun, + int prevent, + iscsi_command_cb cb, void *private_data); +EXTERN struct scsi_task * iscsi_compareandwrite_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 fua_nv, int group_number, @@ -801,6 +805,10 @@ iscsi_startstopunit_sync(struct iscsi_context *iscsi, int lun, int immed, int pcm, int pc, int no_flush, int loej, int start); +EXTERN struct scsi_task * +iscsi_preventallow_sync(struct iscsi_context *iscsi, int lun, + int prevent); + EXTERN struct scsi_task * iscsi_compareandwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, unsigned char *data, uint32_t datalen, int blocksize, diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 94523d2..e1155c8 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -29,6 +29,7 @@ enum scsi_opcode { SCSI_OPCODE_INQUIRY = 0x12, SCSI_OPCODE_MODESENSE6 = 0x1a, SCSI_OPCODE_STARTSTOPUNIT = 0x1b, + SCSI_OPCODE_PREVENTALLOW = 0x1e, SCSI_OPCODE_READCAPACITY10 = 0x25, SCSI_OPCODE_READ10 = 0x28, SCSI_OPCODE_WRITE10 = 0x2A, @@ -142,6 +143,9 @@ struct scsi_startstopunit_params { int loej; int start; }; +struct scsi_preventallow_params { + int prevent; +}; struct scsi_orwrite_params { uint64_t lba; uint32_t num_blocks; @@ -239,6 +243,7 @@ struct scsi_task { struct scsi_write12_params write12; struct scsi_write16_params write16; struct scsi_startstopunit_params startstopunit; + struct scsi_preventallow_params preventallow; struct scsi_orwrite_params orwrite; struct scsi_compareandwrite_params compareandwrite; struct scsi_writeverify10_params writeverify10; @@ -673,6 +678,7 @@ EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int bl 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_startstopunit(int immed, int pcm, int pc, int no_flush, int loej, int start); +EXTERN struct scsi_task *scsi_cdb_preventallow(int prevent); EXTERN struct scsi_task *scsi_cdb_orwrite(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_compareandwrite(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_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number); diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 3c99a9b..e9f400e 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -30,6 +30,8 @@ iscsi_prefetch10_sync iscsi_prefetch10_task iscsi_prefetch16_sync iscsi_prefetch16_task +iscsi_preventallow_sync +iscsi_preventallow_task iscsi_queue_length iscsi_read10_sync iscsi_read10_task @@ -110,6 +112,7 @@ scsi_cdb_get_lba_status scsi_cdb_modesense6 scsi_cdb_prefetch10 scsi_cdb_prefetch16 +scsi_cdb_preventallow scsi_cdb_read10 scsi_cdb_read12 scsi_cdb_read16 diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index c475765..c523c7e 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -28,6 +28,8 @@ iscsi_prefetch10_sync iscsi_prefetch10_task iscsi_prefetch16_sync iscsi_prefetch16_task +iscsi_preventallow_sync +iscsi_preventallow_task iscsi_queue_length iscsi_read10_sync iscsi_read10_task @@ -108,6 +110,7 @@ scsi_cdb_get_lba_status scsi_cdb_modesense6 scsi_cdb_prefetch10 scsi_cdb_prefetch16 +scsi_cdb_preventallow scsi_cdb_read10 scsi_cdb_read12 scsi_cdb_read16 diff --git a/lib/scsi-command.c b/lib/scsi-command.c index 56f2f54..aa1682e 100644 --- a/lib/scsi-command.c +++ b/lib/scsi-command.c @@ -1192,6 +1192,28 @@ iscsi_startstopunit_task(struct iscsi_context *iscsi, int lun, return task; } +struct scsi_task * +iscsi_preventallow_task(struct iscsi_context *iscsi, int lun, + int prevent, + iscsi_command_cb cb, void *private_data) +{ + struct scsi_task *task; + + task = scsi_cdb_preventallow(prevent); + if (task == NULL) { + iscsi_set_error(iscsi, "Out-of-memory: Failed to create " + "PreventAllowMediumRemoval 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_synchronizecache10_task(struct iscsi_context *iscsi, int lun, int lba, int num_blocks, int syncnv, int immed, diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 8f738e5..f7bfa1a 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -1567,6 +1567,33 @@ scsi_cdb_startstopunit(int immed, int pcm, int pc, int no_flush, int loej, int s return task; } +/* + * PREVENTALLOWMEDIUMREMOVAL + */ +struct scsi_task * +scsi_cdb_preventallow(int prevent) +{ + 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_PREVENTALLOW; + + task->cdb[4] = prevent & 0x03; + + task->cdb_size = 6; + task->xfer_dir = SCSI_XFER_NONE; + task->expxferlen = 0; + + task->params.preventallow.prevent = prevent; + + return task; +} + /* * SYNCHRONIZECACHE10 */ diff --git a/lib/sync.c b/lib/sync.c index fdcd401..8363de5 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -419,6 +419,26 @@ iscsi_startstopunit_sync(struct iscsi_context *iscsi, int lun, return state.task; } +struct scsi_task * +iscsi_preventallow_sync(struct iscsi_context *iscsi, int lun, + int prevent) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_preventallow_task(iscsi, lun, prevent, + scsi_sync_cb, &state) == NULL) { + iscsi_set_error(iscsi, + "Failed to send PreventAllowMediumRemoval command"); + return NULL; + } + + event_loop(iscsi, &state); + + return state.task; +} + struct scsi_task * iscsi_synchronizecache16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t num_blocks, int syncnv, int immed)