[stgt] [PATCH] MODE_SENSE: add support for mode subpages
ronnie sahlberg
ronniesahlberg at gmail.com
Fri Jul 27 08:32:33 CEST 2012
ping ?
On Sun, Jul 22, 2012 at 2:13 PM, Ronnie Sahlberg
<ronniesahlberg at gmail.com> wrote:
> Add support for mode subpages.
> Change the modepages from an array of pointers to a linked list
> so that we can store an arbitrary number od mode pages with the same
> page code (but different subpage codes)
>
> Add a simple modepage with a subpage code 0x0a/0x01 which is the
> ControlExtensions subpage.
> Have TCMOS set to 1 in this subpage.
> This value has the following meaning (SPC):
> A timestamp changeable by methods outside this standard (TCMOS)
> bit set to one specifies that the timestamp may
> be initialized by methods outside the scope of this standard.
>
> Which sounds appropriate since root or ntpd can change the
> local time on linux without first asking TGTD and SPC for permission first :-)
>
> Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
> ---
> usr/bs_rdwr.c | 12 +++++++-
> usr/mmc.c | 4 ++-
> usr/sbc.c | 15 +++++++++--
> usr/smc.c | 8 +++--
> usr/spc.c | 76 +++++++++++++++++++++++++++++++++++++-------------------
> usr/spc.h | 4 ++-
> usr/ssc.c | 4 ++-
> usr/target.c | 1 +
> usr/tgtd.h | 3 +-
> 9 files changed, 89 insertions(+), 38 deletions(-)
>
> diff --git a/usr/bs_rdwr.c b/usr/bs_rdwr.c
> index 981ab65..a79dd02 100644
> --- a/usr/bs_rdwr.c
> +++ b/usr/bs_rdwr.c
> @@ -38,6 +38,7 @@
> #include "util.h"
> #include "tgtd.h"
> #include "scsi.h"
> +#include "spc.h"
> #include "bs_thread.h"
>
> static void set_medium_error(int *result, uint8_t *key, uint16_t *asc)
> @@ -156,12 +157,19 @@ write:
> ret = pwrite64(fd, scsi_get_out_buffer(cmd), length,
> offset);
> if (ret == length) {
> + struct mode_pg *pg;
> +
> /*
> * it would be better not to access to pg
> * directy.
> */
> - struct mode_pg *pg = cmd->dev->mode_pgs[0x8];
> -
> + pg = find_mode_page(cmd->dev, 0x08, 0);
> + if (pg == NULL) {
> + result = SAM_STAT_CHECK_CONDITION;
> + key = ILLEGAL_REQUEST;
> + asc = ASC_INVALID_FIELD_IN_CDB;
> + break;
> + }
> if (((cmd->scb[0] != WRITE_6) && (cmd->scb[1] & 0x8)) ||
> !(pg->mode_data[0] & 0x04))
> bs_sync_sync_range(cmd, length, &result, &key,
> diff --git a/usr/mmc.c b/usr/mmc.c
> index 4d81426..d8d4a7b 100644
> --- a/usr/mmc.c
> +++ b/usr/mmc.c
> @@ -2243,7 +2243,9 @@ static tgtadm_err mmc_lu_init(struct scsi_lu *lu)
> /* Caching Page */
> add_mode_page(lu, "8:0:10:0:0:0:0:0:0:0:0:0:0");
> /* Control page */
> - add_mode_page(lu, "10:0:10:2:0:0:0:0:0:0:0:2:0");
> + add_mode_page(lu, "0x0a:0:10:2:0:0:0:0:0:0:0:2:0");
> + /* Control Extensions mode page: TCMOS:1 */
> + add_mode_page(lu, "0x0a:1:0x00:0x1c:0x00:0x00:0x00");
> /* Power Condition */
> add_mode_page(lu, "0x1a:0:10:8:0:0:0:0:0:0:0:0:0");
> /* Informational Exceptions Control page */
> diff --git a/usr/sbc.c b/usr/sbc.c
> index 7a643e1..77f32c4 100644
> --- a/usr/sbc.c
> +++ b/usr/sbc.c
> @@ -69,9 +69,14 @@ static off_t find_next_hole(struct scsi_lu *dev, off_t offset)
> static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *changed)
> {
> uint8_t pcode = data[0] & 0x3f;
> - struct mode_pg *pg = cmd->dev->mode_pgs[pcode];
> + uint8_t subpcode = data[1];
> + struct mode_pg *pg;
> uint8_t old;
>
> + pg = find_mode_page(cmd->dev, pcode, subpcode);
> + if (pg == NULL)
> + return 1;
> +
> eprintf("%x %x\n", pg->mode_data[0], data[2]);
>
> if (pcode == 0x08) {
> @@ -688,11 +693,15 @@ static tgtadm_err sbc_lu_init(struct scsi_lu *lu)
> memset(mask, 0, sizeof(mask));
> mask[0] = 0x4;
>
> - set_mode_page_changeable_mask(lu, 8, mask);
> + set_mode_page_changeable_mask(lu, 8, 0, mask);
> }
>
> /* Control page */
> - add_mode_page(lu, "10:0:10:2:0x10:0:0:0:0:0:0:2:0");
> + add_mode_page(lu, "0x0a:0:10:2:0x10:0:0:0:0:0:0:2:0");
> +
> + /* Control Extensions mode page: TCMOS:1 */
> + add_mode_page(lu, "0x0a:1:5:0x00:0x1c:0x00:0x00:0x00");
> +
> /* Informational Exceptions Control page */
> add_mode_page(lu, "0x1c:0:10:8:0:0:0:0:0:0:0:0:0");
>
> diff --git a/usr/smc.c b/usr/smc.c
> index bbfbfcd..c31a7c7 100644
> --- a/usr/smc.c
> +++ b/usr/smc.c
> @@ -514,7 +514,9 @@ static tgtadm_err smc_lu_init(struct scsi_lu *lu)
> /* Vendor uniq - However most apps seem to call for mode page 0*/
> add_mode_page(lu, "0:0:0");
> /* Control page */
> - add_mode_page(lu, "10:0:10:2:0:0:0:0:0:0:0:2:0");
> + add_mode_page(lu, "0x0a:0:10:2:0:0:0:0:0:0:0:2:0");
> + /* Control Extensions mode page: TCMOS:1 */
> + add_mode_page(lu, "0x0a:1:0x00:0x1c:0x00:0x00:0x00");
> /* Power Condition */
> add_mode_page(lu, "0x1a:0:10:8:0:0:0:0:0:0:0:0:0");
> /* Informational Exceptions Control page */
> @@ -625,7 +627,7 @@ static tgtadm_err add_slt(struct scsi_lu *lu, struct tmp_param *tmp)
> int qnty_save;
> int i;
>
> - pg = lu->mode_pgs[0x1d];
> + pg = find_mode_page(lu, 0x1d, 0);
> if (!pg) {
> dprintf("Failed to find Element Address Assignment mode pg\n");
> return TGTADM_UNKNOWN_ERR;
> @@ -692,7 +694,7 @@ static tgtadm_err config_slot(struct scsi_lu *lu, struct tmp_param *tmp)
> switch(tmp->element_type) {
> case ELEMENT_MEDIUM_TRANSPORT:
> /* If medium has more than one side, set the 'rotate' bit */
> - m = lu->mode_pgs[0x1e];
> + m = find_mode_page(lu, 0x1e, 0);
> if (m) {
> m->mode_data[0] = (tmp->sides > 1) ? 1 : 0;
> adm_err = TGTADM_SUCCESS;
> diff --git a/usr/spc.c b/usr/spc.c
> index c3b4052..1c1f187 100644
> --- a/usr/spc.c
> +++ b/usr/spc.c
> @@ -480,7 +480,7 @@ int spc_mode_select(int host_no, struct scsi_cmd *cmd,
>
> pcode = data[offset] & 0x3f;
>
> - pg = cmd->dev->mode_pgs[pcode];
> + pg = find_mode_page(cmd->dev, pcode, 0);
> if (!pg)
> goto sense;
>
> @@ -525,10 +525,22 @@ sense:
> return SAM_STAT_CHECK_CONDITION;
> }
>
> +struct mode_pg *find_mode_page(struct scsi_lu *lu, uint8_t pcode,
> + uint8_t subpcode)
> +{
> + struct mode_pg *pg;
> +
> + list_for_each_entry(pg, &lu->mode_pages, mode_pg_siblings) {
> + if (pg->pcode == pcode && pg->subpcode == subpcode)
> + return pg;
> + }
> + return NULL;
> +}
> +
> int set_mode_page_changeable_mask(struct scsi_lu *lu, uint8_t pcode,
> - uint8_t *mask)
> + uint8_t subpcode, uint8_t *mask)
> {
> - struct mode_pg *pg = lu->mode_pgs[pcode];
> + struct mode_pg *pg = find_mode_page(lu, pcode, subpcode);
>
> if (pg) {
> memcpy(pg->mode_data + pg->pcode_size, mask, pg->pcode_size);
> @@ -551,18 +563,27 @@ static int build_mode_page(uint8_t *data, struct mode_pg *pg,
> uint8_t pc, uint16_t *alloc_len)
> {
> uint8_t *p;
> - int len;
> + int len, hdr_size;
> uint8_t *mode_data;
>
> len = pg->pcode_size;
> if (*alloc_len >= 2) {
> - data[0] = pg->pcode;
> - data[1] = len;
> + if (!pg->subpcode) {
> + data[0] = pg->pcode;
> + data[1] = len;
> + hdr_size = 2;
> + } else {
> + data[0] = pg->pcode | 0x40;
> + data[1] = pg->subpcode;
> + data[2] = len >> 8;
> + data[3] = len & 0xff;
> + hdr_size = 4;
> + }
> }
> - *alloc_len -= min_t(uint16_t, *alloc_len, 2);
> + *alloc_len -= min_t(uint16_t, *alloc_len, hdr_size);
>
> - p = &data[2];
> - len += 2;
> + p = &data[hdr_size];
> + len += hdr_size;
> if (*alloc_len >= pg->pcode_size) {
> if (pc == 1)
> mode_data = pg->mode_data + pg->pcode_size;
> @@ -599,10 +620,6 @@ int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
> pctrl = (scb[2] & 0xc0) >> 6;
> subpcode = scb[3];
>
> - /* Currently not implemented */
> - if (subpcode)
> - goto sense;
> -
> if (pctrl == 3) {
> asc = ASC_SAVING_PARMS_UNSUP;
> goto sense;
> @@ -633,15 +650,14 @@ int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
> }
>
> if (pcode == 0x3f) {
> - int i;
> - for (i = 0; i < ARRAY_SIZE(cmd->dev->mode_pgs); i++) {
> - pg = cmd->dev->mode_pgs[i];
> - if (pg)
> - len += build_mode_page(data + len, pg, pctrl,
> - &alloc_len);
> + list_for_each_entry(pg,
> + &cmd->dev->mode_pages,
> + mode_pg_siblings) {
> + len += build_mode_page(data + len, pg, pctrl,
> + &alloc_len);
> }
> } else {
> - pg = cmd->dev->mode_pgs[pcode];
> + pg = find_mode_page(cmd->dev, pcode, subpcode);
> if (!pg)
> goto sense;
> len += build_mode_page(data + len, pg, pctrl, &alloc_len);
> @@ -1595,8 +1611,11 @@ tgtadm_err add_mode_page(struct scsi_lu *lu, char *p)
> case 2:
> size = strtol(p, NULL, 0);
>
> - if (lu->mode_pgs[pcode])
> - free(lu->mode_pgs[pcode]);
> + pg = find_mode_page(lu, pcode, subpcode);
> + if (pg) {
> + list_del(&pg->mode_pg_siblings);
> + free(pg);
> + }
>
> pg = alloc_mode_pg(pcode, subpcode, size);
> if (!pg) {
> @@ -1604,7 +1623,7 @@ tgtadm_err add_mode_page(struct scsi_lu *lu, char *p)
> goto exit;
> }
>
> - lu->mode_pgs[pcode] = pg;
> + list_add_tail(&pg->mode_pg_siblings, &lu->mode_pages);
> data = pg->mode_data;
> break;
> default:
> @@ -1898,7 +1917,12 @@ void spc_lu_exit(struct scsi_lu *lu)
> if (lu_vpd[i])
> free(lu_vpd[i]);
>
> - for (i = 0; i < ARRAY_SIZE(lu->mode_pgs); i++)
> - if (lu->mode_pgs[i])
> - free(lu->mode_pgs[i]);
> + while (!list_empty(&lu->mode_pages)) {
> + struct mode_pg *pg;
> + pg = list_first_entry(&lu->mode_pages,
> + struct mode_pg,
> + mode_pg_siblings);
> + list_del(&pg->mode_pg_siblings);
> + free(pg);
> + }
> }
> diff --git a/usr/spc.h b/usr/spc.h
> index 5b88542..0c537e1 100644
> --- a/usr/spc.h
> +++ b/usr/spc.h
> @@ -23,7 +23,9 @@ extern void dump_cdb(struct scsi_cmd *cmd);
> extern int spc_mode_sense(int host_no, struct scsi_cmd *cmd);
> extern tgtadm_err add_mode_page(struct scsi_lu *lu, char *params);
> extern int set_mode_page_changeable_mask(struct scsi_lu *lu, uint8_t pcode,
> - uint8_t *mask);
> + uint8_t subpcode, uint8_t *mask);
> +extern struct mode_pg *find_mode_page(struct scsi_lu *lu,
> + uint8_t pcode, uint8_t subpcode);
> extern int spc_mode_select(int host_no, struct scsi_cmd *cmd,
> int (*update)(struct scsi_cmd *, uint8_t *, int *));
> extern struct vpd *alloc_vpd(uint16_t size);
> diff --git a/usr/ssc.c b/usr/ssc.c
> index 59d2e15..549cba9 100644
> --- a/usr/ssc.c
> +++ b/usr/ssc.c
> @@ -193,7 +193,9 @@ static tgtadm_err ssc_lu_init(struct scsi_lu *lu)
> /* Disconnect page - Mandatory - SPC-4 */
> add_mode_page(lu, "2:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0:0");
> /* Control page - Mandatory - SPC-4 */
> - add_mode_page(lu, "10:0:10:2:0:0:0:0:0:0:0:2:0");
> + add_mode_page(lu, "0x0a:0:10:2:0:0:0:0:0:0:0:2:0");
> + /* Control Extensions mode page: TCMOS:1 */
> + add_mode_page(lu, "0x0a:1:0x00:0x1c:0x00:0x00:0x00");
> /* Data Compression - Mandatory - SSC3 8.3.2 */
> add_mode_page(lu, "15:0:14:0:0:0:0:0:0:0:0:0:0:0:0:0:0");
> /* Device Configuration - Mandatory - SSC3 8.3.3 */
> diff --git a/usr/target.c b/usr/target.c
> index e94c3ed..05d8c59 100644
> --- a/usr/target.c
> +++ b/usr/target.c
> @@ -579,6 +579,7 @@ tgtadm_err tgt_device_create(int tid, int dev_type, uint64_t lun, char *params,
> tgt_cmd_queue_init(&lu->cmd_queue);
> INIT_LIST_HEAD(&lu->registration_list);
> INIT_LIST_HEAD(&lu->lu_itl_info_list);
> + INIT_LIST_HEAD(&lu->mode_pages);
> lu->prgeneration = 0;
> lu->pr_holder = NULL;
>
> diff --git a/usr/tgtd.h b/usr/tgtd.h
> index 8bee2e3..07cd971 100644
> --- a/usr/tgtd.h
> +++ b/usr/tgtd.h
> @@ -168,6 +168,7 @@ struct backingstore_template {
> };
>
> struct mode_pg {
> + struct list_head mode_pg_siblings;
> uint8_t pcode; /* Page code */
> uint8_t subpcode; /* Sub page code */
> int16_t pcode_size; /* Size of page code data. */
> @@ -210,7 +211,7 @@ struct scsi_lu {
> struct target *tgt;
>
> uint8_t mode_block_descriptor[BLOCK_DESCRIPTOR_LEN];
> - struct mode_pg *mode_pgs[0x3f];
> + struct list_head mode_pages;
>
> struct lu_phy_attr attrs;
>
> --
> 1.7.3.1
>
--
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