ping ? On Sun, Jul 22, 2012 at 2:13 PM, Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> 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@xxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html