From: <rsw...@us...> - 2010-04-08 20:56:42
|
Revision: 315 http://iscsitarget.svn.sourceforge.net/iscsitarget/?rev=315&view=rev Author: rswwalker Date: 2010-04-08 20:56:35 +0000 (Thu, 08 Apr 2010) Log Message: ----------- Move the common iotype functions from each iotype to volume.c. Modifies the gen_scsiid to generate either a MD5 hash of the target's IQN plus the volume's LUN, or a concatenation of the target's TID and LUN numbers if no MD5 can be generated. Sets the scsi_sn to the hex of scsi_id if no scsi_sn is provided. Required doubling the size of scsi_sn to accommodate this (2 * SCSI_ID_LEN). Removes the VENDOR_ID from the scsi_id and adds it to the VPD 0x83 request in target_disk.c so one doesn't need to jump over it to modify the scsi_id. Removes the validity checks in VPD 0x80 request in target_disk and moves it to set_scsisn in volume. Changes since rev2: - Fixed bug in volume.c where auto-gen scsi_sn from scsi_id used the SCSI_SN_LEN instead of SCSI_ID_LEN. - Added extra char at the end of scsi_sn for nul terminating character as scsi_sn is a string val and not a binary like scsi_id is, so we need to make sure string funcs don't break. - Moved protocol formatting from set_scsisn to target_disk.c for VPD 80. Signed-off-by: Ross Walker Revision Links: -------------- http://iscsitarget.svn.sourceforge.net/iscsitarget/?rev=2&view=rev Modified Paths: -------------- trunk/include/iet_u.h trunk/kernel/block-io.c trunk/kernel/file-io.c trunk/kernel/iscsi.h trunk/kernel/null-io.c trunk/kernel/target_disk.c trunk/kernel/volume.c trunk/patches/compat-2.6.14-2.6.18.patch trunk/patches/compat-2.6.23.patch Modified: trunk/include/iet_u.h =================================================================== --- trunk/include/iet_u.h 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/include/iet_u.h 2010-04-08 20:56:35 UTC (rev 315) @@ -9,9 +9,8 @@ #define ISCSI_LISTEN_PORT 3260 -#define VENDOR_ID_LEN 8 -#define SCSI_ID_LEN 24 -#define SCSI_SN_LEN 16 +#define SCSI_ID_LEN 16 +#define SCSI_SN_LEN (SCSI_ID_LEN * 2) #ifndef aligned_u64 #define aligned_u64 unsigned long long __attribute__((aligned(8))) Modified: trunk/kernel/block-io.c =================================================================== --- trunk/kernel/block-io.c 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/kernel/block-io.c 2010-04-08 20:56:35 UTC (rev 315) @@ -175,78 +175,21 @@ return err; } -static int -set_scsiid(struct iet_volume *volume, const char *id) -{ - size_t len; - - 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; - } - - memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len); - - return 0; -} - -static void -gen_scsiid(struct iet_volume *volume, struct inode *inode) -{ - int i; - u32 *p; - - strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); - - for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++) - if (volume->scsi_id[i]) - return; - - /* 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 - */ - 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; -} - -static int -set_scsisn(struct iet_volume *volume, const char *sn) -{ - size_t len; - - if ((len = strlen(sn)) > SCSI_SN_LEN) { - eprintk("SCSI SN too long, %zd provided, %u max\n", len, - SCSI_SN_LEN); - return -EINVAL; - } - - memcpy(volume->scsi_sn, sn, len); - - return 0; -} - /* Create an enumeration of our accepted actions */ enum { - Opt_scsiid, Opt_scsisn, Opt_path, Opt_ignore, Opt_err, + opt_scsiid, opt_scsisn, opt_path, opt_ignore, opt_err, }; /* Create a match table using our action enums and their matching options */ static match_table_t tokens = { - {Opt_scsiid, "scsiid=%s"}, - {Opt_scsisn, "scsisn=%s"}, - {Opt_path, "path=%s"}, - {Opt_ignore, "type=%s"}, - {Opt_ignore, "iomode=%s"}, - {Opt_ignore, "blocksize=%s"}, - {Opt_err, NULL}, + {opt_path, "path=%s"}, + {opt_ignore, "scsiid=%s"}, + {opt_ignore, "scsisn=%s"}, + {opt_ignore, "type=%s"}, + {opt_ignore, "iomode=%s"}, + {opt_ignore, "blocksize=%s"}, + {opt_err, NULL}, }; static int @@ -267,27 +210,7 @@ iet_strtolower(p); token = match_token(p, tokens, args); switch (token) { - case Opt_scsiid: - if (!(q = match_strdup(&args[0]))) { - err = -ENOMEM; - goto out; - } - err = set_scsiid(volume, q); - kfree(q); - if (err < 0) - goto out; - break; - case Opt_scsisn: - if (!(q = match_strdup(&args[0]))) { - err = -ENOMEM; - goto out; - } - err = set_scsisn(volume, q); - kfree(q); - if (err < 0) - goto out; - break; - case Opt_path: + case opt_path: if (info->path) { iprintk("Target %s, LUN %u: " "duplicate \"Path\" param\n", @@ -304,7 +227,7 @@ if (err < 0) goto out; break; - case Opt_ignore: + case opt_ignore: break; default: iprintk("Target %s, LUN %u: unknown param %s\n", @@ -375,9 +298,6 @@ volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift; - /* Assign a vendor id, generate scsi id if none exists */ - gen_scsiid(volume, bio_data->bdev->bd_inode); - /* Offer neither write nor read caching */ ClearLURCache(volume); ClearLUWCache(volume); Modified: trunk/kernel/file-io.c =================================================================== --- trunk/kernel/file-io.c 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/kernel/file-io.c 2010-04-08 20:56:35 UTC (rev 315) @@ -125,64 +125,18 @@ return err; } -static int set_scsiid(struct iet_volume *volume, const char *id) -{ - size_t len; - - 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; - } - - memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len); - - return 0; -} - -static void gen_scsiid(struct iet_volume *volume, struct inode *inode) -{ - int i; - u32 *p; - - strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN); - - 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; -} - -static int set_scsisn(struct iet_volume *volume, const char *sn) -{ - size_t len; - - if ((len = strlen(sn)) > SCSI_SN_LEN) { - eprintk("SCSI SN too long, %zd provided, %u max\n", len, - SCSI_SN_LEN); - return -EINVAL; - } - memcpy(volume->scsi_sn, sn, len); - return 0; -} - enum { - Opt_scsiid, Opt_scsisn, Opt_path, Opt_ignore, Opt_err, + opt_path, opt_ignore, opt_err, }; static match_table_t tokens = { - {Opt_scsiid, "scsiid=%s"}, - {Opt_scsisn, "scsisn=%s"}, - {Opt_path, "path=%s"}, - {Opt_ignore, "type=%s"}, - {Opt_ignore, "iomode=%s"}, - {Opt_ignore, "blocksize=%s"}, - {Opt_err, NULL}, + {opt_path, "path=%s"}, + {opt_ignore, "scsiid=%s"}, + {opt_ignore, "scsisn=%s"}, + {opt_ignore, "type=%s"}, + {opt_ignore, "iomode=%s"}, + {opt_ignore, "blocksize=%s"}, + {opt_err, NULL}, }; static int parse_fileio_params(struct iet_volume *volume, char *params) @@ -199,27 +153,7 @@ iet_strtolower(p); token = match_token(p, tokens, args); switch (token) { - case Opt_scsiid: - if (!(q = match_strdup(&args[0]))) { - err = -ENOMEM; - goto out; - } - err = set_scsiid(volume, q); - kfree(q); - if (err < 0) - goto out; - break; - case Opt_scsisn: - if (!(q = match_strdup(&args[0]))) { - err = -ENOMEM; - goto out; - } - err = set_scsisn(volume, q); - kfree(q); - if (err < 0) - goto out; - break; - case Opt_path: + case opt_path: if (info->path) { iprintk("Target %s, LUN %u: " "duplicate \"Path\" param\n", @@ -236,7 +170,7 @@ if (err < 0) goto out; break; - case Opt_ignore: + case opt_ignore: break; default: iprintk("Target %s, LUN %u: unknown param %s\n", @@ -288,8 +222,6 @@ } inode = p->filp->f_dentry->d_inode; - gen_scsiid(lu, inode); - if (S_ISREG(inode->i_mode)) ; else if (S_ISBLK(inode->i_mode)) Modified: trunk/kernel/iscsi.h =================================================================== --- trunk/kernel/iscsi.h 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/kernel/iscsi.h 2010-04-08 20:56:35 UTC (rev 315) @@ -151,7 +151,7 @@ struct iscsi_queue queue; u8 scsi_id[SCSI_ID_LEN]; - u8 scsi_sn[SCSI_SN_LEN]; + u8 scsi_sn[SCSI_SN_LEN + 1]; u32 blk_shift; u64 blk_cnt; Modified: trunk/kernel/null-io.c =================================================================== --- trunk/kernel/null-io.c 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/kernel/null-io.c 2010-04-08 20:56:35 UTC (rev 315) @@ -17,18 +17,20 @@ #include "iotype.h" enum { - Opt_blk_cnt, Opt_ignore, Opt_err, + opt_blk_cnt, opt_ignore, opt_err, }; static match_table_t tokens = { /* alias for compatibility with existing setups and documentation */ - {Opt_blk_cnt, "sectors=%u"}, + {opt_blk_cnt, "sectors=%u"}, /* but actually it is the scsi block count, now that we can * specify the block size. */ - {Opt_blk_cnt, "blocks=%u"}, - {Opt_ignore, "blocksize=%s"}, - {Opt_ignore, "type=%s"}, - {Opt_err, NULL}, + {opt_blk_cnt, "blocks=%u"}, + {opt_ignore, "scsiid=%s"}, + {opt_ignore, "scsisn=%s"}, + {opt_ignore, "blocksize=%s"}, + {opt_ignore, "type=%s"}, + {opt_err, NULL}, }; static int parse_nullio_params(struct iet_volume *volume, char *params) @@ -44,14 +46,14 @@ iet_strtolower(p); token = match_token(p, tokens, args); switch (token) { - case Opt_blk_cnt: + case opt_blk_cnt: q = match_strdup(&args[0]); if (!q) return -ENOMEM; volume->blk_cnt = simple_strtoull(q, NULL, 10); kfree(q); break; - case Opt_ignore: + case opt_ignore: break; default: eprintk("Unknown %s\n", p); Modified: trunk/kernel/target_disk.c =================================================================== --- trunk/kernel/target_disk.c 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/kernel/target_disk.c 2010-04-08 20:56:35 UTC (rev 315) @@ -193,11 +193,11 @@ data[7] = 0x02; memset(data + 8, 0x20, 28); memcpy(data + 8, - VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8)); + VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8)); memcpy(data + 16, - PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16)); + PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16)); memcpy(data + 32, - PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4)); + PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4)); data[58] = 0x03; data[59] = 0x20; data[60] = 0x09; @@ -217,35 +217,34 @@ tio_set(tio, 7, 0); err = 0; } else if (scb[2] == 0x80) { - int len = (cmnd->lun && strlen(cmnd->lun->scsi_sn)) ? - SCSI_SN_LEN : 4; + u32 len = (cmnd->lun) ? SCSI_SN_LEN : 4; data[1] = 0x80; data[3] = len; memset(data + 4, 0x20, len); + if (cmnd->lun) { + size_t offset = SCSI_SN_LEN - + strlen(cmnd->lun->scsi_sn); + memcpy(data + 4 + offset, cmnd->lun->scsi_sn, + strlen(cmnd->lun->scsi_sn)); + } tio_set(tio, len + 4, 0); err = 0; - - if (len == SCSI_SN_LEN) { - char *p, *q; - - p = data + 4 + len - 1; - q = cmnd->lun->scsi_sn + len - 1; - - for (; len > 0; len--, q--) - if (isascii(*q) && isprint(*q)) - *(p--) = *q; - } } else if (scb[2] == 0x83) { - u32 len = SCSI_ID_LEN * sizeof(u8); + u32 len = SCSI_ID_LEN + 8; 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); + if (cmnd->lun) { /* We need this ? */ + memset(data + 8, 0x20, 8); + memcpy(data + 8, VENDOR_ID, + min_t(size_t, strlen(VENDOR_ID), 8)); + memcpy(data + 16, cmnd->lun->scsi_id, + SCSI_ID_LEN); + } tio_set(tio, len + 8, 0); err = 0; } Modified: trunk/kernel/volume.c =================================================================== --- trunk/kernel/volume.c 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/kernel/volume.c 2010-04-08 20:56:35 UTC (rev 315) @@ -24,21 +24,100 @@ } enum { - Opt_type, - Opt_iomode, - Opt_blk_size, - Opt_err, + opt_type, + opt_iomode, + opt_scsiid, + opt_scsisn, + opt_blk_size, + opt_err, }; static match_table_t tokens = { - {Opt_type, "type=%s"}, - {Opt_iomode, "iomode=%s"}, - {Opt_blk_size, "blocksize=%u"}, - {Opt_err, NULL}, + {opt_type, "type=%s"}, + {opt_iomode, "iomode=%s"}, + {opt_scsiid, "scsiid=%s"}, + {opt_scsisn, "scsisn=%s"}, + {opt_blk_size, "blocksize=%u"}, + {opt_err, NULL}, }; -static int set_iotype(struct iet_volume *volume, char *params) +static int set_scsiid(struct iet_volume *volume, const char *id) { + size_t len; + + if ((len = strlen(id)) > SCSI_ID_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max\n", len, + SCSI_ID_LEN); + return -EINVAL; + } + + memcpy(volume->scsi_id, id, len); + + return 0; +} + +static int set_scsisn(struct iet_volume *volume, const char *sn) +{ + size_t len; + int i; + + if ((len = strlen(sn)) > SCSI_SN_LEN) { + eprintk("SCSI SN too long, %zd provided, %u max\n", len, + SCSI_SN_LEN); + return -EINVAL; + } + + for (i = 0; i < len; i++) { + if (!isascii(*(sn + i)) || !isprint(*(sn + i))) { + eprintk("invalid characters in SCSI SN, %s\n", + "only printable ascii characters allowed!"); + return -EINVAL; + } + } + + memcpy(volume->scsi_sn, sn, len); + + return 0; +} + +/* Generate a MD5 hash of the target IQN and LUN number */ +static void gen_scsiid(struct iet_volume *volume) +{ + struct hash_desc hash; + + hash.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + hash.flags = 0; + + if (hash.tfm) { + struct scatterlist sg[2]; + unsigned int nbytes = 0; + + sg_init_table(sg, 2); + + sg_set_buf(&sg[0], volume->target->name, + strlen(volume->target->name)); + nbytes += strlen(volume->target->name); + + sg_set_buf(&sg[1], &volume->lun, sizeof(volume->lun)); + nbytes += sizeof(volume->lun); + + crypto_hash_init(&hash); + crypto_hash_update(&hash, sg, nbytes); + crypto_hash_final(&hash, volume->scsi_id); + + crypto_free_hash(hash.tfm); + } else { + /* If no MD5 available set ID to TID and LUN */ + memcpy(volume->scsi_id, &volume->target->tid, + sizeof(volume->target->tid)); + memcpy(volume->scsi_id + sizeof(volume->target->tid), + &volume->lun, sizeof(volume->lun)); + } + +} + +static int parse_volume_params(struct iet_volume *volume, char *params) +{ int err = 0; unsigned blk_sz; substring_t args[MAX_OPT_ARGS]; @@ -46,6 +125,7 @@ if (!buf) return -ENOMEM; + strncpy(buf, params, PAGE_CACHE_SIZE); while ((p = strsep(&buf, ",")) != NULL) { @@ -56,28 +136,54 @@ iet_strtolower(p); token = match_token(p, tokens, args); switch (token) { - case Opt_type: - if (!(argp = match_strdup(&args[0]))) + case opt_type: + argp = match_strdup(&args[0]); + if (!argp) { err = -ENOMEM; - if (argp && !(volume->iotype = get_iotype(argp))) + break; + } + if (!(volume->iotype = get_iotype(argp))) err = -ENOENT; kfree(argp); break; - case Opt_iomode: - if (!(argp = match_strdup(&args[0]))) + case opt_iomode: + argp = match_strdup(&args[0]); + if (!argp) { err = -ENOMEM; - if (argp && !strcmp(argp, "ro")) + break; + } + if (!strcmp(argp, "ro")) SetLUReadonly(volume); - else if (argp && !strcmp(argp, "wb")) + else if (!strcmp(argp, "wb")) SetLUWCache(volume); + else if (strcmp(argp, "wt")) + err = -EINVAL; kfree(argp); break; - case Opt_blk_size: + case opt_scsiid: argp = match_strdup(&args[0]); if (!argp) { err = -ENOMEM; break; } + err = set_scsiid(volume, argp); + kfree(argp); + break; + case opt_scsisn: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } + err = set_scsisn(volume, argp); + kfree(argp); + break; + case opt_blk_size: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } blk_sz = simple_strtoull(argp, NULL, 10); if (is_power_of_2(blk_sz) && 512 <= blk_sz && blk_sz <= IET_MAX_BLOCK_SIZE) @@ -136,7 +242,7 @@ goto free_args; } - ret = set_iotype(volume, args); + ret = parse_volume_params(volume, args); if (ret < 0) goto free_args; @@ -144,6 +250,17 @@ if (ret < 0) goto free_args; + if (!volume->scsi_id[0]) + gen_scsiid(volume); + + if (!volume->scsi_sn[0]) { + int i; + + for (i = 0; i < SCSI_ID_LEN; i++) + snprintf(volume->scsi_sn + (i * 2), 3, "%02x", + volume->scsi_id[i]); + } + INIT_LIST_HEAD(&volume->queue.wait_list); spin_lock_init(&volume->queue.queue_lock); spin_lock_init(&volume->reserve_lock); Modified: trunk/patches/compat-2.6.14-2.6.18.patch =================================================================== --- trunk/patches/compat-2.6.14-2.6.18.patch 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/patches/compat-2.6.14-2.6.18.patch 2010-04-08 20:56:35 UTC (rev 315) @@ -210,3 +210,43 @@ if (!current->io_context) eprintk("%s\n", "Failed to get IO context"); +--- param/kernel/volume.c 2010-03-03 13:42:04.000000000 -0500 ++++ param/kernel/volume.c.18 2010-03-03 00:13:26.000000000 -0500 +@@ -83,28 +83,26 @@ static int set_scsisn(struct iet_volume + + static void gen_scsiid(struct iet_volume *volume) + { +- struct hash_desc hash; ++ struct crypto_tfm *tfm; + +- hash.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); +- hash.flags = 0; ++ tfm = crypto_alloc_tfm("md5", 0); + +- if (hash.tfm) { ++ if (tfm) { + struct scatterlist sg[2]; +- unsigned int nbytes = 0; + + sg[0].page = virt_to_page(volume->target->name); + sg[0].offset = offset_in_page(volume->target->name); +- nbytes += sg[0].length = strlen(volume->target->name); ++ sg[0].length = strlen(volume->target->name); + + sg[1].page = virt_to_page(&volume->lun); + sg[1].offset = offset_in_page(&volume->lun); +- nbytes += sg[1].length = sizeof(volume->lun); ++ sg[1].length = sizeof(volume->lun); + +- crypto_hash_init(&hash); +- crypto_hash_update(&hash, sg, nbytes); +- crypto_hash_final(&hash, volume->scsi_id); ++ crypto_digest_init(tfm); ++ crypto_digest_update(tfm, sg, 2); ++ crypto_digest_final(tfm, volume->scsi_id); + +- crypto_free_hash(hash.tfm); ++ crypto_free_tfm(tfm); + } else { + /* If no MD5 available set ID to TID and LUN */ + memcpy(volume->scsi_id, volume->target->tid, Modified: trunk/patches/compat-2.6.23.patch =================================================================== --- trunk/patches/compat-2.6.23.patch 2010-04-08 20:49:07 UTC (rev 314) +++ trunk/patches/compat-2.6.23.patch 2010-04-08 20:56:35 UTC (rev 315) @@ -150,3 +150,27 @@ if (!nl) return -ENOMEM; else +--- param/kernel/volume.c 2010-03-03 13:41:36.000000000 -0500 ++++ param/kernel/volume.c 2010-03-03 13:42:04.000000000 -0500 +@@ -92,14 +92,13 @@ static void gen_scsiid(struct iet_volume + struct scatterlist sg[2]; + unsigned int nbytes = 0; + +- sg_init_table(sg, 2); +- +- sg_set_buf(&sg[0], volume->target->name, +- strlen(volume->target->name)); +- nbytes += strlen(volume->target->name); +- +- sg_set_buf(&sg[1], &volume->lun, sizeof(volume->lun)); +- nbytes += sizeof(volume->lun); ++ sg[0].page = virt_to_page(volume->target->name); ++ sg[0].offset = offset_in_page(volume->target->name); ++ nbytes += sg[0].length = strlen(volume->target->name); ++ ++ sg[1].page = virt_to_page(&volume->lun); ++ sg[1].offset = offset_in_page(&volume->lun); ++ nbytes += sg[1].length = sizeof(volume->lun); + + crypto_hash_init(&hash); + crypto_hash_update(&hash, sg, nbytes); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |