[stgt] RFC [PATCH] Implement PERSISTENT RESERVE IN/OUT
Mark Harvey
markh794 at gmail.com
Wed Aug 20 07:23:14 CEST 2008
On Wed, Aug 20, 2008 at 3:18 PM, ronnie sahlberg
<ronniesahlberg at gmail.com> wrote:
> Hi Mark
>
> Just one suggestion.
> These two commands take service actions, and are thus reported in
> "ReportSupportedOperactionCodes" with one entry for each
> opcode/service_action combination.
>
>
> Please have a look at how I implemented service actions by looking at
> the maint_in_service_actions example :
> sbc.c: {spc_maint_in, maint_in_service_actions,},
>
> If you add a similar structure for your service actions it means that
> ReportedSupportedOperationCodes will return correct
> data for your PersistentReservation opcode.
Many thanks.
I'll check it out.
>
> regards
> ronnie sahlberg
>
>
>
> On Wed, Aug 20, 2008 at 3:01 PM, Mark Harvey <markh794 at gmail.com> wrote:
>> Apologies for sending as an attachment... gmail and all.
>>
>> This is an initial attempt to implement PERSISTENT RESERVE IN and
>> PERSISTENT RESERVE OUT.
>>
>> Currently only READ KEY service action will actually return anything.
>> It returns a hard-coded 'ABC1234'.
>>
>> This post is a request for comment before I get too far into coding effort.
>>
>> # lsscsi -g
>> [3:0:0:0] disk USB-HS HTS726060M9AT00 0.01 /dev/sda /dev/sg0
>> [7:0:0:0] storage IET Controller 0001 - /dev/sg1
>> [7:0:0:1] disk QUANTUM HD100 0010 /dev/sdb /dev/sg2
>> [7:0:0:2] tape QUANTUM DLT6000 0010 /dev/st0 /dev/sg3
>> [7:0:0:3] tape QUANTUM DLT6000 0010 /dev/st1 /dev/sg4
>> [7:0:0:4] tape QUANTUM DLT6000 0010 /dev/st2 /dev/sg5
>> [7:0:0:5] mediumx STK L700 0010 - /dev/sg6
>>
>> # sg_persist -i /dev/sg3
>>>> No service action given; assume Persistent Reservations In command
>>>> with Read Keys service action
>> QUANTUM DLT6000 0010
>> Peripheral device type: tape
>> PR generation=0x0, 4 registered reservation keys follow:
>> 0x4142433132333400
>> 0x0
>> 0x0
>> 0x0
>>
>>
>> I'll include in-line for viewing pleasure :)
>>
>> [PATCH 1/2]
>> From 11ad9ee209708f51bd2884598d309b1e7079cdce Mon Sep 17 00:00:00 2001
>> From: Mark Harvey <markh794 at gmail.com>
>> Date: Wed, 20 Aug 2008 14:42:27 +1000
>> Subject: RFC - Implement PERSISTENT RESERVE IN/OUT
>>
>> Implement service action 'READ KEY' which returns
>> a hard-coded string 'ABC1234'
>>
>> Signed-off-by: Mark Harvey <markh794 at gmail.com>
>> ---
>> usr/scsi.h | 5 ++
>> usr/spc.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> usr/spc.h | 2 +
>> usr/tgtd.h | 13 ++++
>> 4 files changed, 251 insertions(+), 0 deletions(-)
>>
>> diff --git a/usr/scsi.h b/usr/scsi.h
>> index 84fadff..a9481a1 100644
>> --- a/usr/scsi.h
>> +++ b/usr/scsi.h
>> @@ -208,6 +208,11 @@
>> #define ASC_POSITION_PAST_BOM 0x3b0c
>> #define ASC_MEDIUM_REMOVAL_PREVENTED 0x5302
>> #define ASC_BAD_MICROCODE_DETECTED 0x8283
>> +#define ASC_INSUFFICENT_RESERVE_RESOURCE 0x5502
>> +#define ASC_INSUFFICENT_RESOURCE 0x5503
>> +#define ASC_INSUFFICENT_REGISTRAT_RESOURCE 0x5504
>> +#define ASC_INSUFFICENT_AC_RESOURCE 0x5505
>> +#define ASC_AUX_MEMORY_OUT_OF_SPACE 0x5506
>>
>> /* Key 6: Unit Attention */
>> #define ASC_NOT_READY_TO_TRANSITION 0x2800
>> diff --git a/usr/spc.c b/usr/spc.c
>> index bd2c975..cc088bf 100644
>> --- a/usr/spc.c
>> +++ b/usr/spc.c
>> @@ -880,6 +880,237 @@ void dump_cdb(struct scsi_cmd *cmd)
>> }
>> }
>>
>> +/**
>> + * SCSI Persistent Reservation
>> + *
>> + * Reference: spc4r16 Ch 5.7
>> + *
>> + * Interesting points:
>> + * - Persistent reservations are not reset by hard reset, lu reset ot I_T loss
>> + * - Optionally, may be retained when power to target is lost
>> + */
>> +
>> +/**
>> + * PERSISTENT RESERVE IN - 5Eh
>> + * Ref: 6.13
>> + *
>> + */
>> +#define PR_IN_READ_KEYS 0
>> +#define PR_IN_READ_RESERVATION 1
>> +#define PR_IN_REPORT_CAPABILITIES 2
>> +#define PR_IN_READ_FULL_STATUS 3
>> +static int spc_pr_read_keys(int host_no, struct scsi_cmd *cmd)
>> +{
>> + uint8_t *buf;
>> + int len;
>> + int cdb_alloc_len;
>> + struct scsi_pr *pr;
>> +
>> + cdb_alloc_len = ((cmd->scb[7] & 0xff) << 8) | (cmd->scb[8] & 0xff);
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> +
>> + buf = scsi_get_in_buffer(cmd);
>> + len = sizeof(cmd->dev->pr.pr_key);
>> + memset(buf, 0, len + 8);
>> +
>> + dprintf("Buf: %p, len: %d, cdb_alloc_len: %d\n",
>> + buf, len, cdb_alloc_len);
>> +
>> + buf[0] = (pr->PRgeneration >> 24) & 0xff;
>> + buf[1] = (pr->PRgeneration >> 16) & 0xff;
>> + buf[2] = (pr->PRgeneration >> 8) & 0xff;
>> + buf[3] = pr->PRgeneration & 0xff;
>> + buf[4] = (len >> 24) & 0xff;
>> + buf[5] = (len >> 16) & 0xff;
>> + buf[6] = (len >> 8) & 0xff;
>> + buf[7] = len & 0xff;
>> +
>> + strcpy(buf + 8, "ABC1234");
>> + memcpy(scsi_get_in_buffer(cmd), buf, min(cdb_alloc_len, len + 8));
>> +
>> + scsi_set_in_resid_by_actual(cmd, len + 8);
>> +
>> + return SAM_STAT_GOOD;
>> +}
>> +
>> +static int spc_pr_read_reservation(int host_no, struct scsi_cmd *cmd)
>> +{
>> + dprintf("**** Called ****\n");
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_report_capabilities(int host_no, struct scsi_cmd *cmd)
>> +{
>> + dprintf("**** Called ****\n");
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_read_full_status(int host_no, struct scsi_cmd *cmd)
>> +{
>> + dprintf("**** Called ****\n");
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +struct service_action pr_in_service_actions[] = {
>> + {PR_IN_READ_KEYS, spc_pr_read_keys},
>> + {PR_IN_READ_RESERVATION, spc_pr_read_reservation},
>> + {PR_IN_REPORT_CAPABILITIES, spc_pr_report_capabilities},
>> + {PR_IN_READ_FULL_STATUS, spc_pr_read_full_status},
>> + {0, NULL}
>> +};
>> +
>> +int persistent_reserve_in(int host_no, struct scsi_cmd *cmd)
>> +{
>> + uint8_t action;
>> + struct service_action *service_action;
>> +
>> + action = cmd->scb[1] & 0x1f;
>> + service_action = find_service_action(pr_in_service_actions, action);
>> +
>> + if (!service_action) {
>> + scsi_set_in_resid_by_actual(cmd, 0);
>> + sense_data_build(cmd, ILLEGAL_REQUEST,
>> + ASC_INVALID_FIELD_IN_CDB);
>> + return SAM_STAT_CHECK_CONDITION;
>> + }
>> +
>> + return service_action->cmd_perform(host_no, cmd);
>> +}
>> +
>> +/**
>> + * PERSISTENT RESERVE OUT - 5Fh
>> + * Ref: 6.14
>> + */
>> +#define PR_OUT_REGISTER 0
>> +#define PR_OUT_RESERVE 1
>> +#define PR_OUT_RELEASE 2
>> +#define PR_OUT_CLEAR 3
>> +#define PR_OUT_PREEMPT 4
>> +#define PR_OUT_PREEMPT_ABORT 5
>> +#define PR_OUT_REGISTER_IGNORE 6
>> +#define PR_OUT_REGISTER_MOVE 7
>> +
>> +static int spc_pr_register(int host_no, struct scsi_cmd *cmd)
>> +{
>> + struct scsi_pr *pr;
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> + pr->PRgeneration += 1;
>> +
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_reserve(int host_no, struct scsi_cmd *cmd)
>> +{
>> + dprintf("**** Called ****\n");
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_release(int host_no, struct scsi_cmd *cmd)
>> +{
>> + dprintf("**** Called ****\n");
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_clear(int host_no, struct scsi_cmd *cmd)
>> +{
>> + struct scsi_pr *pr;
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> + pr->PRgeneration += 1;
>> +
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_preempt(int host_no, struct scsi_cmd *cmd)
>> +{
>> + struct scsi_pr *pr;
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> + pr->PRgeneration += 1;
>> +
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_preempt_abort(int host_no, struct scsi_cmd *cmd)
>> +{
>> + struct scsi_pr *pr;
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> + pr->PRgeneration += 1;
>> +
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_register_ignore(int host_no, struct scsi_cmd *cmd)
>> +{
>> + struct scsi_pr *pr;
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> + pr->PRgeneration += 1;
>> +
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int spc_pr_register_move(int host_no, struct scsi_cmd *cmd)
>> +{
>> + struct scsi_pr *pr;
>> +
>> + dprintf("**** Called ****\n");
>> + pr = &cmd->dev->pr;
>> + pr->PRgeneration += 1;
>> +
>> + sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
>> + return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +struct service_action pr_out_service_actions[] = {
>> + {PR_OUT_REGISTER, spc_pr_register},
>> + {PR_OUT_RESERVE, spc_pr_reserve},
>> + {PR_OUT_RELEASE, spc_pr_release},
>> + {PR_OUT_CLEAR, spc_pr_clear},
>> + {PR_OUT_PREEMPT, spc_pr_preempt},
>> + {PR_OUT_PREEMPT_ABORT, spc_pr_preempt_abort},
>> + {PR_OUT_REGISTER_IGNORE, spc_pr_register_ignore},
>> + {PR_OUT_REGISTER_MOVE, spc_pr_register_move},
>> + {0, NULL}
>> +};
>> +
>> +int persistent_reserve_out(int host_no, struct scsi_cmd *cmd)
>> +{
>> + uint8_t action;
>> + struct service_action *service_action;
>> +
>> + action = cmd->scb[1] & 0x1f;
>> + service_action = find_service_action(pr_out_service_actions, action);
>> +
>> + if (!service_action) {
>> + scsi_set_in_resid_by_actual(cmd, 0);
>> + sense_data_build(cmd, ILLEGAL_REQUEST,
>> + ASC_INVALID_FIELD_IN_CDB);
>> + return SAM_STAT_CHECK_CONDITION;
>> + }
>> +
>> + return service_action->cmd_perform(host_no, cmd);
>> +}
>> +
>> int spc_illegal_op(int host_no, struct scsi_cmd *cmd)
>> {
>> dump_cdb(cmd);
>> diff --git a/usr/spc.h b/usr/spc.h
>> index 8fe3e3c..bdc3c1f 100644
>> --- a/usr/spc.h
>> +++ b/usr/spc.h
>> @@ -9,6 +9,8 @@ extern int spc_start_stop(int host_no, struct scsi_cmd *cmd);
>> extern int spc_test_unit(int host_no, struct scsi_cmd *cmd);
>> extern int spc_request_sense(int host_no, struct scsi_cmd *cmd);
>> extern int spc_illegal_op(int host_no, struct scsi_cmd *cmd);
>> +extern int persistent_reserve_in(int host_no, struct scsi_cmd *cmd);
>> +extern int persistent_reserve_out(int host_no, struct scsi_cmd *cmd);
>> extern int spc_lu_init(struct scsi_lu *lu);
>>
>> typedef int (match_fn_t)(struct scsi_lu *lu, char *params);
>> diff --git a/usr/tgtd.h b/usr/tgtd.h
>> index 4febcd3..d2c7135 100644
>> --- a/usr/tgtd.h
>> +++ b/usr/tgtd.h
>> @@ -19,6 +19,11 @@
>>
>> #define VENDOR_ID "IET"
>>
>> +/* 8 byte reservation key size */
>> +#define PR_KEY_SZ 8
>> +/* Number of PR keys we can store at any one time */
>> +#define PR_RESERVATION_SZ 4
>> +
>> #define _TAB1 " "
>> #define _TAB2 _TAB1 _TAB1
>> #define _TAB3 _TAB1 _TAB1 _TAB1
>> @@ -126,6 +131,12 @@ struct mode_pg {
>> uint8_t mode_data[0]; /* Rest of mode page info */
>> };
>>
>> +struct scsi_pr {
>> + /* Persistent Reservation Generation */
>> + uint32_t PRgeneration;
>> + uint8_t pr_key[PR_RESERVATION_SZ][PR_KEY_SZ];
>> +};
>> +
>> struct scsi_lu {
>> int fd;
>> uint64_t addr; /* persistent mapped address */
>> @@ -150,6 +161,8 @@ struct scsi_lu {
>> uint8_t mode_block_descriptor[BLOCK_DESCRIPTOR_LEN];
>> struct mode_pg *mode_pgs[0x3f];
>>
>> + struct scsi_pr pr;
>> +
>> struct lu_phy_attr attrs;
>>
>> /* A pointer for each modules private use.
>> --
>> 1.5.6
>>
>> [PATCH 2/2]
>> From 68c454d2d7f1b64f9dbce9410e5c2c8500d6ceb3 Mon Sep 17 00:00:00 2001
>> From: Mark Harvey <markh794 at gmail.com>
>> Date: Wed, 20 Aug 2008 14:45:30 +1000
>> Subject: Add persistent reserve in/out to ssc module
>>
>> Signed-off-by: Mark Harvey <markh794 at gmail.com>
>> ---
>> usr/ssc.c | 4 ++--
>> 1 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/usr/ssc.c b/usr/ssc.c
>> index 2630a6a..6dbdc0b 100644
>> --- a/usr/ssc.c
>> +++ b/usr/ssc.c
>> @@ -251,8 +251,8 @@ static struct device_type_template ssc_template = {
>> {spc_illegal_op,},
>> {spc_illegal_op,},
>> {spc_illegal_op,},
>> - {spc_illegal_op,},
>> - {spc_illegal_op,},
>> + {persistent_reserve_in,},
>> + {persistent_reserve_out,},
>>
>> [0x60 ... 0x7f] = {spc_illegal_op,},
>>
>> --
>> 1.5.6
>>
>
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list