|
View:
New views
2 Messages
—
Rating Filter:
Alert me
|
|
|
[PATCH2/2] Add multiples SCSI IDs, hexadecimal IDs for all and ASCII for T10- Changed scsi id to multiple ids
- Added parameters ScsiIdT10, ScsiIdEUI64, ScsiIdNAA. Old ScsiId points to ScsiIdT10 - All scsi id accepts hex inputs (0xAAAA). The ascii input is implemented only for T10. - Modified scsi_id attribute in iet_target to a multiple struct scsi_id_desc. - Defined constants related to scsi id - gen_scsid now uses set_scsid to set a T10 Id when not defined by config (no behavior changed) - The presence check of scsi id is done outside gen_scsi. - Docs updates I changed the set_scsiid to parse_scsiid. This method check if the input is hex or ascii. For ascii, it switches for each type (EUI64, T10, NAA). However, currently just T10 is implemented. Both hex and t10_ascii at the end calls set_scsiid that is responsible just to write the scsi_id_desc. I don't know how to test multiple scsi_id but at least it sends the current byte order. In client I got \x00\x83\x00\x19\x01\x01\x00\x03\x33\x33\x33\x01\x02\x00\x03\x33\x33\x33\x01\x03\x00\x07\x33\x33\x33\x33\x33\x33\x33 Page 0x83 Size: 0x19 (4+3 + 4+3 + 4+7 = 25 = 0x19) ID(T10): 333 ID(EUI64): 333 ID(NAA): 3333333 -- Luiz Angelo Daros de Luca luizluca@... ICQ: 19290419 I Know, "Where you wanted to go today", but I decided to stop here instead! MS Windows diff -ru iscsitarget-param/doc/manpages/ietd.conf.5 iscsitarget/doc/manpages/ietd.conf.5 --- iscsitarget-param/doc/manpages/ietd.conf.5 2008-03-31 16:49:22.000000000 -0300 +++ iscsitarget/doc/manpages/ietd.conf.5 2008-05-07 15:35:40.935751123 -0300 @@ -124,7 +124,7 @@ .I <username> given. .TP -.B Lun <lun> Path=<device>,Type=(fileio|blockio)[,ScsiId=<scsi_id>][,ScsiSN=<scsi_sn>][,IOMode=(wb|ro)] | Sectors=<size>,Type=nullio +.B Lun <lun> Path=<device>,Type=(fileio|blockio)[,ScsiIdT10=<scsi_id>][,ScsiIdEUI64=<scsi_id>][,ScsiIdNAA=<scsi_id>][,ScsiSN=<scsi_sn>][,IOMode=(wb|ro)] | Sectors=<size>,Type=nullio Parameters after <lun> should not contain any blank space character except the first blank space after <lun> is needed. .br @@ -161,10 +161,11 @@ .I <scsi_id> can be specified to assign a unique ID to the iSCSI volume. This is useful e.g. in conjunction with a multipath\-aware initiator host accessing the same .I <device> -through several targets. -The +through several targets. SCSI ID controls the content of VPD 0x83 and can be defined as T10, EUI64 and NAA types. All SCSI ID types permits hexadecimal (0xAABBCC...) entries. The hexadecimal .I <scsi_id> -must not exceed 16 characters and controls the content of VPD 0x83. The +when converted to binary must not exceed 24 bytes. The T10 also permits ASCII values that will be prefixed with vendor string ("IET\\0\\0\\0\\0\\0"). This ASCII +.I <scsi_id> +must not exceed 16 characters. The .I <scsi_sn> must not exceed 16 characters and controls the content VPD 0x80. .br diff -ru iscsitarget-param/include/iet_u.h iscsitarget/include/iet_u.h --- iscsitarget-param/include/iet_u.h 2008-04-02 20:01:37.000000000 -0300 +++ iscsitarget/include/iet_u.h 2008-05-07 15:36:56.335647110 -0300 @@ -9,10 +9,6 @@ #define ISCSI_LISTEN_PORT 3260 -#define VENDOR_ID_LEN 8 -#define SCSI_ID_LEN 24 -#define SCSI_SN_LEN 16 - #ifndef aligned_u64 #define aligned_u64 unsigned long long __attribute__((aligned(8))) #endif @@ -136,4 +132,33 @@ #define ISCSI_PARAM_SET _IOW('i', 12, struct iscsi_param_info) #define ISCSI_PARAM_GET _IOWR('i', 13, struct iscsi_param_info) +/* + * SCSI ID Code Set values. + */ +#define SCSI_ID_BINARY 1 +#define SCSI_ID_ASCII 2 + +/* + * id type values of id descriptors. These are assumed to fit in 4 bits. + */ +/* Code Description Reference */ +#define SCSI_ID_VENDOR_SPECIFIC 0 +#define SCSI_ID_T10_VENDOR 1 +#define SCSI_ID_EUI_64 2 +#define SCSI_ID_NAA 3 +/* + * #define SCSI_ID_REL_TARGET_PORT_ID 4 + * #define SCSI_ID_TARGET_PORT_GROUP 5 + * #define SCSI_ID_LOGICAL_UNIT_GROUP 6 + * #define SCSI_ID_MD5_LOGICAL_UNIT_ID 7 + * #define SCSI_ID_SCSI_NAME_STRING 8 + * */ +#define SCSI_ID_COUNT 4 + +#define SCSI_ID_LEN 24 +#define SCSI_SN_LEN 16 + +/* T10 constants */ +#define SCSI_ID_T10_VENDOR_LEN 8 + #endif diff -ru iscsitarget-param/kernel/block-io.c iscsitarget/kernel/block-io.c --- iscsitarget-param/kernel/block-io.c 2008-05-02 19:52:27.000000000 -0300 +++ iscsitarget/kernel/block-io.c 2008-05-06 18:00:16.000000000 -0300 @@ -173,29 +173,29 @@ return err; } -static void +static int gen_scsiid(struct iet_volume *volume, struct inode *inode) { - int i; - u32 *p; - - strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); + char *p; + u32 *p32; - for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) - if (volume->scsi_id[i]) - return; + p = kzalloc(SCSI_ID_LEN, GFP_KERNEL); + strncpy (p, VENDOR_ID, strlen(VENDOR_ID)); /* If a scsi id doesn't exist generate a 16 byte one: * Bytes 1-4: target type * Bytes 5-8: target id - * Bytes 9-12: inode number + * Bytes 9-12: lun * Bytes 13-16: device type */ - p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN); - *(p + 0) = volume->target->trgt_param.target_type; - *(p + 1) = volume->target->tid; - *(p + 2) = volume->lun; - *(p + 3) = (unsigned int) inode->i_sb->s_dev; + p32 = (u32*)(p + SCSI_ID_T10_VENDOR_LEN); + *(p32 + 0) = volume->target->trgt_param.target_type; + *(p32 + 1) = volume->target->tid; + *(p32 + 2) = volume->lun; + *(p32 + 3) = (unsigned int) inode->i_sb->s_dev; + + /* In the future, set_scsiid should use vendor + buf */ + return set_scsiid(volume, p, SCSI_ID_LEN, SCSI_ID_T10_VENDOR); } /* Create an enumeration of our accepted actions */ @@ -273,7 +273,11 @@ } /* Assign a vendor id, generate scsi id if none exists */ - gen_scsiid(volume, bio_data->bdev->bd_inode); + if (scsiid_defined(volume) < 0) { + if ((err = gen_scsiid(volume, bio_data->bdev->bd_inode)) < 0) { + goto out; + } + } volume->blk_shift = SECTOR_SIZE_BITS; volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift; diff -ru iscsitarget-param/kernel/file-io.c iscsitarget/kernel/file-io.c --- iscsitarget-param/kernel/file-io.c 2008-05-02 19:52:27.000000000 -0300 +++ iscsitarget/kernel/file-io.c 2008-05-06 17:59:35.000000000 -0300 @@ -123,22 +123,29 @@ return err; } -static void gen_scsiid(struct iet_volume *volume, struct inode *inode) +static int +gen_scsiid(struct iet_volume *volume, struct inode *inode) { - int i; - u32 *p; + char *p; + u32 *p32; - strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); + p = kzalloc(SCSI_ID_LEN, GFP_KERNEL); + strncpy (p, VENDOR_ID, strlen(VENDOR_ID)); - for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) - if (volume->scsi_id[i]) - return; - - p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN); - *(p + 0) = volume->target->trgt_param.target_type; - *(p + 1) = volume->target->tid; - *(p + 2) = (unsigned int) inode->i_ino; - *(p + 3) = (unsigned int) inode->i_sb->s_dev; + /* If a scsi id doesn't exist generate a 16 byte one: + * Bytes 1-4: target type + * Bytes 5-8: target id + * Bytes 9-12: inode number + * Bytes 13-16: device type + */ + p32 = (u32*)(p + SCSI_ID_T10_VENDOR_LEN); + *(p32 + 0) = volume->target->trgt_param.target_type; + *(p32 + 1) = volume->target->tid; + *(p32 + 2) = (unsigned int) inode->i_ino; + *(p32 + 3) = (unsigned int) inode->i_sb->s_dev; + + /* In the future, set_scsiid should use vendor + buf */ + return set_scsiid(volume, p, SCSI_ID_LEN, SCSI_ID_T10_VENDOR); } enum { @@ -210,7 +217,12 @@ } inode = p->filp->f_dentry->d_inode; - gen_scsiid(lu, inode); + /* Assign a vendor id, generate scsi id if none exists */ + if (scsiid_defined(lu) < 0) { + if ((err = gen_scsiid(lu, inode)) < 0) { + goto out; + } + } if (S_ISREG(inode->i_mode)) ; diff -ru iscsitarget-param/kernel/iscsi.h iscsitarget/kernel/iscsi.h --- iscsitarget-param/kernel/iscsi.h 2008-05-02 19:52:28.000000000 -0300 +++ iscsitarget/kernel/iscsi.h 2008-05-06 20:34:09.000000000 -0300 @@ -125,6 +125,13 @@ int active_cnt; }; +struct scsi_id_desc { + u8 type; + u8 codeset; + size_t len; + u8 id[SCSI_ID_LEN]; +}; + struct iet_volume { u32 lun; @@ -136,7 +143,7 @@ struct iscsi_queue queue; - u8 scsi_id[SCSI_ID_LEN]; + struct scsi_id_desc scsi_id[SCSI_ID_COUNT]; u8 scsi_sn[SCSI_SN_LEN]; u32 blk_shift; @@ -341,6 +348,8 @@ int parse_volume_params(struct iet_volume *volume, const char *params, int (*parse_fn)(struct iet_volume *, char *)); int volume_do_param(struct iet_volume *volume, char *param); +int scsiid_defined(struct iet_volume *volume); +int set_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type); /* tio.c */ extern int tio_init(void); diff -ru iscsitarget-param/kernel/target_disk.c iscsitarget/kernel/target_disk.c --- iscsitarget-param/kernel/target_disk.c 2008-03-31 16:49:22.000000000 -0300 +++ iscsitarget/kernel/target_disk.c 2008-05-07 14:39:46.638147302 -0300 @@ -222,16 +222,61 @@ *(p--) = *q; } } else if (scb[2] == 0x83) { - u32 len = SCSI_ID_LEN * sizeof(u8); + /* Here multiple scsiid should be returned, + * one for any scsi id defined (scsi_id_len>0) + * Currently, just the first found will be returned + */ + u16 len = 0; + u8 *id_data; + int i; data[1] = 0x83; - data[3] = len + 4; - data[4] = 0x1; - data[5] = 0x1; - data[7] = len; - if (cmnd->lun) /* We need this ? */ - memcpy(data + 8, cmnd->lun->scsi_id, len); - tio_set(tio, len + 8, 0); + + /* By now, there is SCSI_ID_COUNT fixed scsi_id slots. + * + * We need to check for cmnd->lun because clients + * can inquiry luns that does not exists + * Is it rigth to get here without lun? */ + for (i = 0; i < SCSI_ID_COUNT && cmnd->lun; i++) { + struct scsi_id_desc *id_desc = cmnd->lun->scsi_id + i; + int new_len; + + /* 4 is Dev id VPD page header */ + id_data = data + (4 + len); + + if (id_desc->len == 0) { + /* id not defined */ + continue; + } + + /* 4 is id description header */ + new_len = len + 4 + id_desc->len; + + if (new_len > min_t(long unsigned int, tio->pg_cnt * PAGE_SIZE, scb[4])) { + eprintk("Page too small to fit scsi id type %d." + " Required: %u Avaiable: %lu:tio/%u:scb\n", + id_desc->type, new_len, tio->pg_cnt * PAGE_SIZE, + scb[4]); + continue; + } + + /* protocol identifier is on the higher 4bits but unused */ + id_data[0] = id_desc->codeset; + /* piv and assoc is on the higher 4bits but unused */ + id_data[1] = id_desc->type; + /* reserved id_desc[2] */ + id_data[3] = id_desc->len; + /* 4 is id description header */ + memcpy(id_data + 4, id_desc->id, id_desc->len); + /* next id description */ + len = new_len; + } + + /* avoid endianess */ + data[2] = len >> 8; + data[3] = len & 0xFF; + + tio_set(tio, len + 4, 0); err = 0; } } diff -ru iscsitarget-param/kernel/volume.c iscsitarget/kernel/volume.c --- iscsitarget-param/kernel/volume.c 2008-05-02 19:52:28.000000000 -0300 +++ iscsitarget/kernel/volume.c 2008-05-07 14:00:40.864805234 -0300 @@ -29,6 +29,9 @@ Opt_scsiid, Opt_scsisn, Opt_err, + Opt_scsiid_t10vendor, + Opt_scsiid_eui64, + Opt_scsiid_naa, }; static match_table_t iotokens = { @@ -89,6 +92,9 @@ {Opt_ignore, "IOMode=%s"}, {Opt_scsiid, "ScsiId=%s"}, {Opt_scsisn, "ScsiSN=%s"}, + {Opt_scsiid_t10vendor, "ScsiIdT10=%s"}, + {Opt_scsiid_eui64, "ScsiIdEUI64=%s"}, + {Opt_scsiid_naa, "ScsiIdNAA=%s"}, {Opt_err, NULL}, }; @@ -113,7 +119,7 @@ continue; if ((err = parse_fn(volume, param)) < 0) { - eprintk("Param failed! %d \n", err); + eprintk("Param failed! %d for lun %d\n", err, volume->lun); break; } } @@ -123,22 +129,125 @@ return err; } -static int -set_scsiid(struct iet_volume *volume, const char *id) +int scsiid_defined(struct iet_volume *volume) { - size_t len; + int i=0; - if ((len = strlen(id)) > SCSI_ID_LEN - VENDOR_ID_LEN) { - eprintk("SCSI ID too long, %zd provided, %u max\n", len, - SCSI_ID_LEN - VENDOR_ID_LEN); - return -EINVAL; + for (i=0; i<SCSI_ID_COUNT; i++) { + if (volume->scsi_id[i].len>0) { + return i; + } } + return -ENOENT; +}; - memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len); +int set_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type) +{ + if (len > SCSI_ID_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max in lun %d\n", len, + SCSI_ID_LEN, volume->lun); + return -EINVAL; + } + memcpy(volume->scsi_id[scsi_id_type].id, id, len); + volume->scsi_id[scsi_id_type].len = len; + volume->scsi_id[scsi_id_type].codeset = SCSI_ID_BINARY; + volume->scsi_id[scsi_id_type].type = scsi_id_type; return 0; } +int set_hex_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type) +{ + + int i, err; + char *buf; + char hex[3]; + + if (len % 2) { + eprintk("SCSI ID hex has odd number of characters in lun %d.", volume->lun); + return -EINVAL; + } + + if (len / 2 > SCSI_ID_LEN) { + eprintk("SCSI ID when converted to binary is too long in lun %d," + " %zd provided, %u max\n", volume->lun, len/2, + SCSI_ID_LEN); + return -EINVAL; + } + + if (!(buf = kmalloc(len/2, GFP_KERNEL))) { + return -ENOMEM; + } + + hex[2]='\0'; + for (i=0; i < (len / 2); i++) { + uint byte; + + hex[0]=id[i*2]; + hex[1]=id[i*2+1]; + + if (!sscanf(hex,"%2X", &byte)) { + eprintk("%s is not good a good hex code in lun %d\n", hex, volume->lun); + return -EINVAL; + } + + buf[i] = byte; + } + + err = set_scsiid(volume, buf, i, scsi_id_type); + + kfree(buf); + return err; +} + +int set_t10_scsiid(struct iet_volume *volume, const char *id, size_t len) +{ + int err; + char *t10_id; + + if (len > SCSI_ID_LEN - SCSI_ID_T10_VENDOR_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max in lun %d\n", len, + SCSI_ID_LEN - SCSI_ID_T10_VENDOR_LEN, volume->lun); + return -EINVAL; + } + + if (!(t10_id = kmalloc(SCSI_ID_LEN, GFP_KERNEL))) { + return -ENOMEM; + } + + memset(t10_id, 0 , SCSI_ID_LEN); + /* Prefix with vendor ID */ + memcpy(t10_id, VENDOR_ID, sizeof(VENDOR_ID)); + /* Copy user set ID */ + strncpy(t10_id + SCSI_ID_T10_VENDOR_LEN, id, SCSI_ID_LEN - SCSI_ID_T10_VENDOR_LEN); + + err = set_scsiid(volume, t10_id, SCSI_ID_LEN, SCSI_ID_T10_VENDOR); + + kfree(t10_id); + return err; +} + +int parse_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type) +{ + int err; + + if ((len > 2) && (id[0]=='0') && (id[1]=='x')) { + err = set_hex_scsiid(volume, id + 2, len - 2, scsi_id_type); + } else { + switch (scsi_id_type) { + case SCSI_ID_T10_VENDOR: + err = set_t10_scsiid(volume, id, len); + break; + default: + eprintk("Only hex input allowed for this SCSI ID type (%d) used in lun %d\n", + scsi_id_type, volume->lun); + err = -EINVAL; + } + } + + return err; +} + static int set_scsisn(struct iet_volume *volume, const char *sn) { size_t len; @@ -166,11 +275,28 @@ switch (token) { case Opt_scsiid: + case Opt_scsiid_t10vendor: + if (!(value = match_strdup(&args[0]))) { + err = -ENOMEM; + break; + } + err = parse_scsiid(volume, value, strlen(value), SCSI_ID_T10_VENDOR); + kfree(value); + break; + case Opt_scsiid_eui64: + if (!(value = match_strdup(&args[0]))) { + err = -ENOMEM; + break; + } + err = parse_scsiid(volume, value, strlen(value), SCSI_ID_EUI_64); + kfree(value); + break; + case Opt_scsiid_naa: if (!(value = match_strdup(&args[0]))) { err = -ENOMEM; break; } - err = set_scsiid(volume, value); + err = parse_scsiid(volume, value, strlen(value), SCSI_ID_NAA); kfree(value); break; case Opt_scsisn: ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ Iscsitarget-devel mailing list Iscsitarget-devel@... https://lists.sourceforge.net/lists/listinfo/iscsitarget-devel |
|
|
Fwd: [PATCH2/2] Add multiples SCSI IDs, hexadecimal IDs for all and ASCII for T10Update to current trunk
- Changed scsi id to multiple ids - Added parameters ScsiIdT10, ScsiIdEUI64, ScsiIdNAA. Old ScsiId points to ScsiIdT10 - All scsi id accepts hex inputs (0xAAAA). The ascii input is implemented only for T10. - Modified scsi_id attribute in iet_target to a multiple struct scsi_id_desc. - Defined constants related to scsi id - gen_scsid now uses set_scsid to set a T10 Id when not defined by config (no behavior changed) - The presence check of scsi id is done outside gen_scsi. - Docs updates I changed the set_scsiid to parse_scsiid. This method check if the input is hex or ascii. For ascii, it switches for each type (EUI64, T10, NAA). However, currently just T10 is implemented. Both hex and t10_ascii at the end calls set_scsiid that is responsible just to write the scsi_id_desc. I don't know how to test multiple scsi_id but at least it sends the current byte order. In client I got \x00\x83\x00\x19\x01\x01\x00\x03\x33\x33\x33\x01\x02\x00\x03\x33\x33\x33\x01\x03\x00\x07\x33\x33\x33\x33\x33\x33\x33 Page 0x83 Size: 0x19 (4+3 + 4+3 + 4+7 = 25 = 0x19) ID(T10): 333 ID(EUI64): 333 ID(NAA): 3333333 -- Luiz Angelo Daros de Luca luizluca@... ICQ: 19290419 I Know, "Where you wanted to go today", but I decided to stop here instead! MS Windows diff -u -r iscsitarget-param//doc/manpages/ietd.conf.5 iscsitarget/doc/manpages/ietd.conf.5 --- iscsitarget-param//doc/manpages/ietd.conf.5 2008-03-31 16:49:22.000000000 -0300 +++ iscsitarget/doc/manpages/ietd.conf.5 2008-06-23 18:09:47.000000000 -0300 @@ -124,7 +124,7 @@ .I <username> given. .TP -.B Lun <lun> Path=<device>,Type=(fileio|blockio)[,ScsiId=<scsi_id>][,ScsiSN=<scsi_sn>][,IOMode=(wb|ro)] | Sectors=<size>,Type=nullio +.B Lun <lun> Path=<device>,Type=(fileio|blockio)[,ScsiIdT10=<scsi_id>][,ScsiIdEUI64=<scsi_id>][,ScsiIdNAA=<scsi_id>][,ScsiSN=<scsi_sn>][,IOMode=(wb|ro)] | Sectors=<size>,Type=nullio Parameters after <lun> should not contain any blank space character except the first blank space after <lun> is needed. .br @@ -161,10 +161,11 @@ .I <scsi_id> can be specified to assign a unique ID to the iSCSI volume. This is useful e.g. in conjunction with a multipath\-aware initiator host accessing the same .I <device> -through several targets. -The +through several targets. SCSI ID controls the content of VPD 0x83 and can be defined as T10, EUI64 and NAA types. All SCSI ID types permits hexadecimal (0xAABBCC...) entries. The hexadecimal .I <scsi_id> -must not exceed 16 characters and controls the content of VPD 0x83. The +when converted to binary must not exceed 24 bytes. The T10 also permits ASCII values that will be prefixed with vendor string ("IET\\0\\0\\0\\0\\0"). This ASCII +.I <scsi_id> +must not exceed 16 characters. The .I <scsi_sn> must not exceed 16 characters and controls the content VPD 0x80. .br diff -u -r iscsitarget-param//include/iet_u.h iscsitarget/include/iet_u.h --- iscsitarget-param//include/iet_u.h 2008-04-02 20:01:37.000000000 -0300 +++ iscsitarget/include/iet_u.h 2008-06-23 18:09:47.000000000 -0300 @@ -9,10 +9,6 @@ #define ISCSI_LISTEN_PORT 3260 -#define VENDOR_ID_LEN 8 -#define SCSI_ID_LEN 24 -#define SCSI_SN_LEN 16 - #ifndef aligned_u64 #define aligned_u64 unsigned long long __attribute__((aligned(8))) #endif @@ -136,4 +132,33 @@ #define ISCSI_PARAM_SET _IOW('i', 12, struct iscsi_param_info) #define ISCSI_PARAM_GET _IOWR('i', 13, struct iscsi_param_info) +/* + * SCSI ID Code Set values. + */ +#define SCSI_ID_BINARY 1 +#define SCSI_ID_ASCII 2 + +/* + * id type values of id descriptors. These are assumed to fit in 4 bits. + */ +/* Code Description Reference */ +#define SCSI_ID_VENDOR_SPECIFIC 0 +#define SCSI_ID_T10_VENDOR 1 +#define SCSI_ID_EUI_64 2 +#define SCSI_ID_NAA 3 +/* + * #define SCSI_ID_REL_TARGET_PORT_ID 4 + * #define SCSI_ID_TARGET_PORT_GROUP 5 + * #define SCSI_ID_LOGICAL_UNIT_GROUP 6 + * #define SCSI_ID_MD5_LOGICAL_UNIT_ID 7 + * #define SCSI_ID_SCSI_NAME_STRING 8 + * */ +#define SCSI_ID_COUNT 4 + +#define SCSI_ID_LEN 24 +#define SCSI_SN_LEN 16 + +/* T10 constants */ +#define SCSI_ID_T10_VENDOR_LEN 8 + #endif diff -u -r iscsitarget-param//kernel/block-io.c iscsitarget/kernel/block-io.c --- iscsitarget-param//kernel/block-io.c 2008-06-23 18:06:16.000000000 -0300 +++ iscsitarget/kernel/block-io.c 2008-06-23 18:09:47.000000000 -0300 @@ -174,29 +174,29 @@ return err; } -static void +static int gen_scsiid(struct iet_volume *volume, struct inode *inode) { - int i; - u32 *p; - - strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); + char *p; + u32 *p32; - for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) - if (volume->scsi_id[i]) - return; + p = kzalloc(SCSI_ID_LEN, GFP_KERNEL); + strncpy (p, VENDOR_ID, strlen(VENDOR_ID)); /* If a scsi id doesn't exist generate a 16 byte one: * Bytes 1-4: target type * Bytes 5-8: target id - * Bytes 9-12: inode number + * Bytes 9-12: lun * Bytes 13-16: device type */ - p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN); - *(p + 0) = volume->target->trgt_param.target_type; - *(p + 1) = volume->target->tid; - *(p + 2) = volume->lun; - *(p + 3) = (unsigned int) inode->i_sb->s_dev; + p32 = (u32*)(p + SCSI_ID_T10_VENDOR_LEN); + *(p32 + 0) = volume->target->trgt_param.target_type; + *(p32 + 1) = volume->target->tid; + *(p32 + 2) = volume->lun; + *(p32 + 3) = (unsigned int) inode->i_sb->s_dev; + + /* In the future, set_scsiid should use vendor + buf */ + return set_scsiid(volume, p, SCSI_ID_LEN, SCSI_ID_T10_VENDOR); } /* Create an enumeration of our accepted actions */ @@ -282,7 +282,11 @@ } /* Assign a vendor id, generate scsi id if none exists */ - gen_scsiid(volume, bio_data->bdev->bd_inode); + if (scsiid_defined(volume) < 0) { + if ((err = gen_scsiid(volume, bio_data->bdev->bd_inode)) < 0) { + goto out; + } + } volume->blk_shift = SECTOR_SIZE_BITS; volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift; diff -u -r iscsitarget-param//kernel/file-io.c iscsitarget/kernel/file-io.c --- iscsitarget-param//kernel/file-io.c 2008-06-23 18:08:09.000000000 -0300 +++ iscsitarget/kernel/file-io.c 2008-06-23 18:09:47.000000000 -0300 @@ -124,22 +124,29 @@ return err; } -static void gen_scsiid(struct iet_volume *volume, struct inode *inode) +static int +gen_scsiid(struct iet_volume *volume, struct inode *inode) { - int i; - u32 *p; + char *p; + u32 *p32; - strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); + p = kzalloc(SCSI_ID_LEN, GFP_KERNEL); + strncpy (p, VENDOR_ID, strlen(VENDOR_ID)); - for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) - if (volume->scsi_id[i]) - return; - - p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN); - *(p + 0) = volume->target->trgt_param.target_type; - *(p + 1) = volume->target->tid; - *(p + 2) = (unsigned int) inode->i_ino; - *(p + 3) = (unsigned int) inode->i_sb->s_dev; + /* If a scsi id doesn't exist generate a 16 byte one: + * Bytes 1-4: target type + * Bytes 5-8: target id + * Bytes 9-12: inode number + * Bytes 13-16: device type + */ + p32 = (u32*)(p + SCSI_ID_T10_VENDOR_LEN); + *(p32 + 0) = volume->target->trgt_param.target_type; + *(p32 + 1) = volume->target->tid; + *(p32 + 2) = (unsigned int) inode->i_ino; + *(p32 + 3) = (unsigned int) inode->i_sb->s_dev; + + /* In the future, set_scsiid should use vendor + buf */ + return set_scsiid(volume, p, SCSI_ID_LEN, SCSI_ID_T10_VENDOR); } enum { @@ -219,7 +226,12 @@ } inode = p->filp->f_dentry->d_inode; - gen_scsiid(lu, inode); + /* Assign a vendor id, generate scsi id if none exists */ + if (scsiid_defined(lu) < 0) { + if ((err = gen_scsiid(lu, inode)) < 0) { + goto out; + } + } if (S_ISREG(inode->i_mode)) ; diff -u -r iscsitarget-param//kernel/iscsi.h iscsitarget/kernel/iscsi.h --- iscsitarget-param//kernel/iscsi.h 2008-06-23 17:23:58.000000000 -0300 +++ iscsitarget/kernel/iscsi.h 2008-06-23 18:09:47.000000000 -0300 @@ -125,6 +125,13 @@ int active_cnt; }; +struct scsi_id_desc { + u8 type; + u8 codeset; + size_t len; + u8 id[SCSI_ID_LEN]; +}; + struct iet_volume { u32 lun; @@ -136,7 +143,7 @@ struct iscsi_queue queue; - u8 scsi_id[SCSI_ID_LEN]; + struct scsi_id_desc scsi_id[SCSI_ID_COUNT]; u8 scsi_sn[SCSI_SN_LEN]; u32 blk_shift; @@ -341,6 +348,8 @@ int parse_volume_params(struct iet_volume *volume, const char *params, int (*parse_fn)(struct iet_volume *, char *)); int volume_do_param(struct iet_volume *volume, char *param); +int scsiid_defined(struct iet_volume *volume); +int set_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type); /* tio.c */ extern int tio_init(void); diff -u -r iscsitarget-param//kernel/target_disk.c iscsitarget/kernel/target_disk.c --- iscsitarget-param//kernel/target_disk.c 2008-06-23 16:49:56.000000000 -0300 +++ iscsitarget/kernel/target_disk.c 2008-06-23 18:09:47.000000000 -0300 @@ -223,16 +223,61 @@ *(p--) = *q; } } else if (scb[2] == 0x83) { - u32 len = SCSI_ID_LEN * sizeof(u8); + /* Here multiple scsiid should be returned, + * one for any scsi id defined (scsi_id_len>0) + * Currently, just the first found will be returned + */ + u16 len = 0; + u8 *id_data; + int i; data[1] = 0x83; - data[3] = len + 4; - data[4] = 0x1; - data[5] = 0x1; - data[7] = len; - if (cmnd->lun) /* We need this ? */ - memcpy(data + 8, cmnd->lun->scsi_id, len); - tio_set(tio, len + 8, 0); + + /* By now, there is SCSI_ID_COUNT fixed scsi_id slots. + * + * We need to check for cmnd->lun because clients + * can inquiry luns that does not exists + * Is it rigth to get here without lun? */ + for (i = 0; i < SCSI_ID_COUNT && cmnd->lun; i++) { + struct scsi_id_desc *id_desc = cmnd->lun->scsi_id + i; + int new_len; + + /* 4 is Dev id VPD page header */ + id_data = data + (4 + len); + + if (id_desc->len == 0) { + /* id not defined */ + continue; + } + + /* 4 is id description header */ + new_len = len + 4 + id_desc->len; + + if (new_len > min_t(long unsigned int, tio->pg_cnt * PAGE_SIZE, scb[4])) { + eprintk("Page too small to fit scsi id type %d." + " Required: %u Avaiable: %lu:tio/%u:scb\n", + id_desc->type, new_len, tio->pg_cnt * PAGE_SIZE, + scb[4]); + continue; + } + + /* protocol identifier is on the higher 4bits but unused */ + id_data[0] = id_desc->codeset; + /* piv and assoc is on the higher 4bits but unused */ + id_data[1] = id_desc->type; + /* reserved id_desc[2] */ + id_data[3] = id_desc->len; + /* 4 is id description header */ + memcpy(id_data + 4, id_desc->id, id_desc->len); + /* next id description */ + len = new_len; + } + + /* avoid endianess */ + data[2] = len >> 8; + data[3] = len & 0xFF; + + tio_set(tio, len + 4, 0); err = 0; } } diff -u -r iscsitarget-param//kernel/volume.c iscsitarget/kernel/volume.c --- iscsitarget-param//kernel/volume.c 2008-06-23 17:23:58.000000000 -0300 +++ iscsitarget/kernel/volume.c 2008-06-23 18:09:47.000000000 -0300 @@ -30,6 +30,9 @@ Opt_scsiid, Opt_scsisn, Opt_err, + Opt_scsiid_t10vendor, + Opt_scsiid_eui64, + Opt_scsiid_naa, }; static match_table_t iotokens = { @@ -90,6 +93,9 @@ {Opt_ignore, "IOMode=%s"}, {Opt_scsiid, "ScsiId=%s"}, {Opt_scsisn, "ScsiSN=%s"}, + {Opt_scsiid_t10vendor, "ScsiIdT10=%s"}, + {Opt_scsiid_eui64, "ScsiIdEUI64=%s"}, + {Opt_scsiid_naa, "ScsiIdNAA=%s"}, {Opt_err, NULL}, }; @@ -114,7 +120,7 @@ continue; if ((err = parse_fn(volume, param)) < 0) { - eprintk("Param failed! %d \n", err); + eprintk("Param failed! %d for lun %d\n", err, volume->lun); break; } } @@ -124,22 +130,125 @@ return err; } -static int -set_scsiid(struct iet_volume *volume, const char *id) +int scsiid_defined(struct iet_volume *volume) { - size_t len; + int i=0; - if ((len = strlen(id)) > SCSI_ID_LEN - VENDOR_ID_LEN) { - eprintk("SCSI ID too long, %zd provided, %u max\n", len, - SCSI_ID_LEN - VENDOR_ID_LEN); - return -EINVAL; + for (i=0; i<SCSI_ID_COUNT; i++) { + if (volume->scsi_id[i].len>0) { + return i; + } } + return -ENOENT; +}; - memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len); +int set_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type) +{ + if (len > SCSI_ID_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max in lun %d\n", len, + SCSI_ID_LEN, volume->lun); + return -EINVAL; + } + memcpy(volume->scsi_id[scsi_id_type].id, id, len); + volume->scsi_id[scsi_id_type].len = len; + volume->scsi_id[scsi_id_type].codeset = SCSI_ID_BINARY; + volume->scsi_id[scsi_id_type].type = scsi_id_type; return 0; } +int set_hex_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type) +{ + + int i, err; + char *buf; + char hex[3]; + + if (len % 2) { + eprintk("SCSI ID hex has odd number of characters in lun %d.", volume->lun); + return -EINVAL; + } + + if (len / 2 > SCSI_ID_LEN) { + eprintk("SCSI ID when converted to binary is too long in lun %d," + " %zd provided, %u max\n", volume->lun, len/2, + SCSI_ID_LEN); + return -EINVAL; + } + + if (!(buf = kmalloc(len/2, GFP_KERNEL))) { + return -ENOMEM; + } + + hex[2]='\0'; + for (i=0; i < (len / 2); i++) { + uint byte; + + hex[0]=id[i*2]; + hex[1]=id[i*2+1]; + + if (!sscanf(hex,"%2X", &byte)) { + eprintk("%s is not good a good hex code in lun %d\n", hex, volume->lun); + return -EINVAL; + } + + buf[i] = byte; + } + + err = set_scsiid(volume, buf, i, scsi_id_type); + + kfree(buf); + return err; +} + +int set_t10_scsiid(struct iet_volume *volume, const char *id, size_t len) +{ + int err; + char *t10_id; + + if (len > SCSI_ID_LEN - SCSI_ID_T10_VENDOR_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max in lun %d\n", len, + SCSI_ID_LEN - SCSI_ID_T10_VENDOR_LEN, volume->lun); + return -EINVAL; + } + + if (!(t10_id = kmalloc(SCSI_ID_LEN, GFP_KERNEL))) { + return -ENOMEM; + } + + memset(t10_id, 0 , SCSI_ID_LEN); + /* Prefix with vendor ID */ + memcpy(t10_id, VENDOR_ID, sizeof(VENDOR_ID)); + /* Copy user set ID */ + strncpy(t10_id + SCSI_ID_T10_VENDOR_LEN, id, SCSI_ID_LEN - SCSI_ID_T10_VENDOR_LEN); + + err = set_scsiid(volume, t10_id, SCSI_ID_LEN, SCSI_ID_T10_VENDOR); + + kfree(t10_id); + return err; +} + +int parse_scsiid(struct iet_volume *volume, const char *id, size_t len, int scsi_id_type) +{ + int err; + + if ((len > 2) && (id[0]=='0') && (id[1]=='x')) { + err = set_hex_scsiid(volume, id + 2, len - 2, scsi_id_type); + } else { + switch (scsi_id_type) { + case SCSI_ID_T10_VENDOR: + err = set_t10_scsiid(volume, id, len); + break; + default: + eprintk("Only hex input allowed for this SCSI ID type (%d) used in lun %d\n", + scsi_id_type, volume->lun); + err = -EINVAL; + } + } + + return err; +} + static int set_scsisn(struct iet_volume *volume, const char *sn) { size_t len; @@ -167,11 +276,28 @@ switch (token) { case Opt_scsiid: + case Opt_scsiid_t10vendor: + if (!(value = match_strdup(&args[0]))) { + err = -ENOMEM; + break; + } + err = parse_scsiid(volume, value, strlen(value), SCSI_ID_T10_VENDOR); + kfree(value); + break; + case Opt_scsiid_eui64: + if (!(value = match_strdup(&args[0]))) { + err = -ENOMEM; + break; + } + err = parse_scsiid(volume, value, strlen(value), SCSI_ID_EUI_64); + kfree(value); + break; + case Opt_scsiid_naa: if (!(value = match_strdup(&args[0]))) { err = -ENOMEM; break; } - err = set_scsiid(volume, value); + err = parse_scsiid(volume, value, strlen(value), SCSI_ID_NAA); kfree(value); break; case Opt_scsisn: ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ Iscsitarget-devel mailing list Iscsitarget-devel@... https://lists.sourceforge.net/lists/listinfo/iscsitarget-devel |
| Free Forum Powered by Nabble | Forum Help |