[Stgt-devel] [Patch 1/1] Add support for VPD pages 80h - ffh
FUJITA Tomonori
tomof
Sun Sep 16 17:33:46 CEST 2007
On Wed, 05 Sep 2007 17:54:14 +1000
Mark Harvey <markh794 at gmail.com> wrote:
> Re-submit of patch with suggested improvements.
>
> - Added pointer struct target to scsi_lu struct
> - Added lu_exit() to free allocation of VPD pages
> - Removed osd from test startup script
> - Removed osd specific VPD pages B0h and B1h
>
> - Passes checkpatch.pl sanity check.
Merged, Thanks! Sorry about the delay again.
Here are some comments.
> +/** Protocol Identifier Values
> + * 0 Fibre Channel (FCP-2)
> + * 1 Parallel SCSI (SPI-5)
We use the following style:
> +/*
> + * Protocol Identifier Values
> + *
> + * 0 Fibre Channel (FCP-2)
> + * 1 Parallel SCSI (SPI-5)
> +static int valid_vpd(struct vpd **lu_vpd, uint8_t page)
> +{
> + if (lu_vpd[page & 0x7f])
> + return 1;
I think that we use 0x7f and 0x80 at too many places. I put new macros
for them.
> + return 0;
> +}
> +
> +void update_vpd_80(struct scsi_lu *lu, void *sn)
> +{
> + struct vpd *vpd_pg = lu->attrs.lu_vpd[0];
> + char *data = (char *)vpd_pg->data;
> +
> + snprintf(data, SCSI_SN_LEN, "%-8s", (char *)sn);
This doesn't work. We need right-aligned ASCII data.
> +}
> +
> +void update_vpd_83(struct scsi_lu *lu, void *id)
> +{
> + struct vpd *vpd_pg = lu->attrs.lu_vpd[3];
> + uint8_t *data = vpd_pg->data;
> +
> + data[0] = (PIV_ISCSI << 4) | INQ_CODE_ASCII;
> + data[1] = PIV_VALID | ASS_TGT_PORT | DESG_VENDOR;
> + data[3] = SCSI_ID_LEN;
> +
> + strncpy((char *)data + 4, id, SCSI_ID_LEN);
> +}
> +
> int spc_inquiry(int host_no, struct scsi_cmd *cmd)
> {
> int len = 0, ret = SAM_STAT_CHECK_CONDITION;
> @@ -47,6 +138,7 @@ int spc_inquiry(int host_no, struct scsi_cmd *cmd)
> uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
> uint8_t devtype = 0;
> struct lu_phy_attr *attrs;
> + struct vpd *vpd_pg;
>
> if (((scb[1] & 0x3) == 0x3) || (!(scb[1] & 0x3) && scb[2]))
> goto sense;
> @@ -98,43 +190,35 @@ int spc_inquiry(int host_no, struct scsi_cmd *cmd)
> } else if (scb[1] & 0x1) {
> /* EVPD bit set */
> if (scb[2] == 0x0) {
> + int i, j, tmp;
> +
> + i = 5;
> + tmp = 1;
> data[0] = devtype;
> - data[1] = 0x0;
> - data[3] = 3;
> + data[1] = 0;
> + data[2] = 0;
> + for (j = 0; j < 0x80; j++) {
> + if (attrs->lu_vpd[j]) {
> + data[i] = j | 0x80;
> + tmp++;
> + i++;
> + }
> + }
I use a more common way here.
> + data[3] = tmp;
> data[4] = 0x0;
> - data[5] = 0x80;
> - data[6] = 0x83;
> - len = 7;
> + len = tmp + 4;
> ret = SAM_STAT_GOOD;
> - } else if (scb[2] == 0x80) {
> - int tmp = SCSI_SN_LEN;
> -
> - data[1] = 0x80;
> - data[3] = SCSI_SN_LEN;
> - memset(data + 4, 0x20, 4);
> - len = 4 + SCSI_SN_LEN;
> - ret = SAM_STAT_GOOD;
> -
> - if (strlen(attrs->scsi_sn)) {
> - uint8_t *p;
> - char *q;
> + } else if (valid_vpd(attrs->lu_vpd, scb[2])) {
> + int tmp;
> + vpd_pg = attrs->lu_vpd[scb[2] & 0x7f];
> + tmp = vpd_pg->size;
>
> - p = data + 4 + tmp - 1;
> - q = attrs->scsi_sn + SCSI_SN_LEN - 1;
> - for (; tmp > 0; tmp--, q)
> - *(p--) = *(q--);
> - }
> - } else if (scb[2] == 0x83) {
> - int tmp = SCSI_ID_LEN;
> -
> - data[1] = 0x83;
> - data[3] = tmp + 4;
> - data[4] = 0x1;
> - data[5] = 0x1;
> - data[7] = tmp;
> - strncpy((char *) data + 8, attrs->scsi_id, SCSI_ID_LEN);
> -
> - len = tmp + 8;
> + data[0] = devtype;
> + data[1] = scb[2];
> + data[2] = (tmp >> 8);
> + data[3] = tmp & 0xff;
> + memcpy(&data[4], vpd_pg->data, tmp);
> + len = tmp + 4;
> ret = SAM_STAT_GOOD;
> }
> }
> @@ -358,6 +442,19 @@ int spc_request_sense(int host_no, struct scsi_cmd *cmd)
> return SAM_STAT_GOOD;
> }
>
> +struct vpd *alloc_vpd(uint16_t size)
> +{
> + struct vpd *vpd_pg;
> +
> + vpd_pg = zalloc(sizeof(struct vpd) + size);
> + if (!vpd_pg)
> + return NULL;
> +
> + vpd_pg->size = size;
> +
> + return vpd_pg;
> +}
> +
> static struct mode_pg *alloc_mode_pg(uint8_t pcode, uint8_t subpcode,
> uint16_t size)
> {
> @@ -500,6 +597,11 @@ int lu_config(struct scsi_lu *lu, char *params, match_fn_t *fn)
> int err = TGTADM_SUCCESS;
> char *p;
> char buf[256];
> + struct lu_phy_attr *attrs;
> + struct vpd **lu_vpd;
> +
> + attrs = &lu->attrs;
> + lu_vpd = attrs->lu_vpd;
>
> if (!strncmp("targetOps", params, 9))
> params = params + 10;
> @@ -512,36 +614,38 @@ int lu_config(struct scsi_lu *lu, char *params, match_fn_t *fn)
> token = match_token(p, tokens, args);
> switch (token) {
> case Opt_scsi_id:
> - match_strncpy(lu->attrs.scsi_id, &args[0],
> - sizeof(lu->attrs.scsi_id));
> + match_strncpy(attrs->scsi_id, &args[0],
> + sizeof(attrs->scsi_id));
Wrong tabs. Should be:
+ match_strncpy(attrs->scsi_id, &args[0],
+ sizeof(attrs->scsi_id));
> + lu_vpd[3]->vpd_update(lu, attrs->scsi_id);
> break;
> case Opt_scsi_sn:
> - match_strncpy(lu->attrs.scsi_sn, &args[0],
> - sizeof(lu->attrs.scsi_sn));
> + match_strncpy(attrs->scsi_sn, &args[0],
> + sizeof(attrs->scsi_sn));
> + lu_vpd[0]->vpd_update(lu, attrs->scsi_sn);
> break;
> case Opt_vendor_id:
> - match_strncpy(lu->attrs.vendor_id, &args[0],
> - sizeof(lu->attrs.vendor_id));
> + match_strncpy(attrs->vendor_id, &args[0],
> + sizeof(attrs->vendor_id));
> break;
> case Opt_product_id:
> - match_strncpy(lu->attrs.product_id, &args[0],
> - sizeof(lu->attrs.product_id));
> + match_strncpy(attrs->product_id, &args[0],
> + sizeof(attrs->product_id));
> break;
> case Opt_product_rev:
> - match_strncpy(lu->attrs.product_rev, &args[0],
> - sizeof(lu->attrs.product_rev));
> + match_strncpy(attrs->product_rev, &args[0],
> + sizeof(attrs->product_rev));
> break;
> case Opt_sense_format:
> match_strncpy(buf, &args[0], sizeof(buf));
> - lu->attrs.sense_format = atoi(buf);
> + attrs->sense_format = atoi(buf);
> break;
> case Opt_removable:
> match_strncpy(buf, &args[0], sizeof(buf));
> - lu->attrs.removable = atoi(buf);
> + attrs->removable = atoi(buf);
> break;
> case Opt_online:
> match_strncpy(buf, &args[0], sizeof(buf));
> - lu->attrs.online = atoi(buf);
> + attrs->online = atoi(buf);
> break;
> case Opt_mode_page:
> match_strncpy(buf, &args[0], sizeof(buf));
> @@ -561,10 +665,34 @@ int spc_lu_config(struct scsi_lu *lu, char *params)
>
> int spc_lu_init(struct scsi_lu *lu)
> {
> + struct vpd **lu_vpd = lu->attrs.lu_vpd;
> + struct target *tgt = lu->tgt;
> + int pg;
> +
> + lu->attrs.device_type = lu->dev_type_template.type;
> + lu->attrs.qualifier = 0x0;
> +
> snprintf(lu->attrs.vendor_id, sizeof(lu->attrs.vendor_id),
> "%-16s", VENDOR_ID);
> snprintf(lu->attrs.product_rev, sizeof(lu->attrs.product_rev),
> "%s", "0001");
> + snprintf(lu->attrs.scsi_id, sizeof(lu->attrs.scsi_id),
> + "deadbeaf%d:%" PRIu64, tgt->tid, lu->lun);
> + snprintf(lu->attrs.scsi_sn, sizeof(lu->attrs.scsi_sn),
> + "beaf%d%" PRIu64, tgt->tid, lu->lun);
> +
> + /* VPD page 0x80 */
> + pg = 0x80 & 0x7f;
> + lu_vpd[pg] = alloc_vpd(SCSI_SN_LEN);
> + lu_vpd[pg]->vpd_update = update_vpd_80;
> + lu_vpd[pg]->vpd_update(lu, lu->attrs.scsi_sn);
> +
> + /* VPD page 0x83 */
> + pg = 0x83 & 0x7f;
> + lu_vpd[pg] = alloc_vpd(SCSI_ID_LEN + 4); /* +Designator descriptor len*/
> + lu_vpd[pg]->vpd_update = update_vpd_83;
> + lu_vpd[pg]->vpd_update(lu, lu->attrs.scsi_id);
> +
> lu->attrs.removable = 0;
> lu->attrs.sense_format = 0;
> lu->attrs.online = 0;
> @@ -572,3 +700,15 @@ int spc_lu_init(struct scsi_lu *lu)
>
> return 0;
> }
> +
> +void spc_lu_exit(struct scsi_lu *lu)
> +{
> + int i;
> + struct vpd **lu_vpd = lu->attrs.lu_vpd;
> +
> + for (i = 0; i < 0x80; i++)
> + if (lu_vpd[i])
> + free(lu_vpd[i]);
> +
> +}
> +
> diff --git a/usr/spc.h b/usr/spc.h
> index 1cc8623..dfb8987 100644
> --- a/usr/spc.h
> +++ b/usr/spc.h
> @@ -12,8 +12,10 @@ extern int spc_lu_init(struct scsi_lu *lu);
> typedef int (match_fn_t)(struct scsi_lu *lu, char *params);
> extern int lu_config(struct scsi_lu *lu, char *params, match_fn_t *);
> extern int spc_lu_config(struct scsi_lu *lu, char *params);
> +extern void spc_lu_exit(struct scsi_lu *lu);
> extern void dump_cdb(struct scsi_cmd *cmd);
> extern int spc_mode_sense(int host_no, struct scsi_cmd *cmd);
> extern int add_mode_page(struct scsi_lu *lu, char *params);
> +extern struct vpd *alloc_vpd(uint16_t size);
>
> #endif
> diff --git a/usr/target.c b/usr/target.c
> index 2474d05..22eec0b 100644
> --- a/usr/target.c
> +++ b/usr/target.c
> @@ -261,12 +261,14 @@ int tgt_device_create(int tid, int dev_type, uint64_t lun, char *args, int backi
> goto free_lu;
> }
>
> + lu->tgt = target;
> +
> lu->lun = lun;
> lu->lu_state = SCSI_LU_RUNNING;
> tgt_cmd_queue_init(&lu->cmd_queue);
>
> if (lu->dev_type_template.lu_init) {
> - ret = lu->dev_type_template.lu_init(lu);
> + ret = lu->dev_type_template.lu_init(lu);
> if (ret)
> goto free_lu;
> }
> @@ -285,13 +287,6 @@ int tgt_device_create(int tid, int dev_type, uint64_t lun, char *args, int backi
> goto free_lu;
> }
>
> - lu->attrs.device_type = lu->dev_type_template.type;
> - lu->attrs.qualifier = 0x0;
> - snprintf(lu->attrs.scsi_id, sizeof(lu->attrs.scsi_id),
> - "deadbeaf%d:%" PRIu64, tid, lun);
> - snprintf(lu->attrs.scsi_sn, sizeof(lu->attrs.scsi_sn),
> - "beaf%d%" PRIu64, tid, lun);
> -
> if (tgt_drivers[target->lid]->lu_create)
> tgt_drivers[target->lid]->lu_create(lu);
>
> diff --git a/usr/tgtd.h b/usr/tgtd.h
> index c39b9c2..45bd8f6 100644
> --- a/usr/tgtd.h
> +++ b/usr/tgtd.h
> @@ -36,6 +36,15 @@ struct tgt_cmd_queue {
> struct list_head queue;
> };
>
> +struct scsi_lu;
> +struct scsi_cmd;
> +
> +struct vpd {
> + uint16_t size;
> + void (*vpd_update)(struct scsi_lu *lu, void *data);
> + uint8_t data[0];
> +};
> +
> struct lu_phy_attr {
> char scsi_id[SCSI_ID_LEN + 1];
> char scsi_sn[SCSI_SN_LEN + 1];
> @@ -52,10 +61,9 @@ struct lu_phy_attr {
> char online; /* Logical Unit online */
> char reset; /* Power-on or reset has occured */
> char sense_format; /* Descrptor format sense data supported */
> -};
>
> -struct scsi_lu;
> -struct scsi_cmd;
> + struct vpd *lu_vpd[0x80]; /* VPD pages 0x80 -> 0xff masked with 0x80*/
> +};
>
> struct device_type_operations {
> int (*cmd_perform)(int host_no, struct scsi_cmd *cmd);
> @@ -109,6 +117,8 @@ struct scsi_lu {
>
> struct backingstore_template *bst;
>
> + struct target *tgt;
> +
> uint8_t mode_block_descriptor[BLOCK_DESCRIPTOR_LEN];
> struct mode_pg *mode_pgs[0x3f];
>
> --
> 1.5.2.3
>
>
>
>
> _______________________________________________
> Stgt-devel mailing list
> Stgt-devel at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/stgt-devel
More information about the stgt
mailing list