Deeply reworked patch from Mehmet Ali Cer <mehmet.ali.cer@gmail.com> implementing...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 18 Mar 2010 18:17:06 +0000 (18:17 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 18 Mar 2010 18:17:06 +0000 (18:17 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1558 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/include/scst.h
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_proc.c
scst/src/scst_sysfs.c
scst/src/scst_targ.c

index 7dc48ff..5588de7 100644 (file)
@@ -2076,6 +2076,8 @@ struct scst_acg {
 
        struct kobject *luns_kobj;
        struct kobject *initiators_kobj;
+
+       unsigned int addr_method;
 };
 
 /*
index d5976ce..337972f 100644 (file)
@@ -1107,7 +1107,7 @@ static struct scst_aen *scst_alloc_aen(struct scst_session *sess,
        aen->sess = sess;
        scst_sess_get(sess);
 
-       aen->lun = scst_pack_lun(unpacked_lun);
+       aen->lun = scst_pack_lun(unpacked_lun, sess->acg->addr_method);
 
 out:
        TRACE_EXIT_HRES((unsigned long)aen);
@@ -2162,6 +2162,8 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
                goto out_free;
        }
 
+       acg->addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
+
 #ifdef CONFIG_SCST_PROC
        TRACE_DBG("Adding acg %s to scst_acg_list", acg_name);
        list_add_tail(&acg->acg_list_entry, &scst_acg_list);
@@ -4259,13 +4261,25 @@ out:
 }
 EXPORT_SYMBOL(scst_get_cdb_info);
 
-/* Packs SCST LUN back to SCSI form using peripheral device addressing method */
-uint64_t scst_pack_lun(const uint64_t lun)
+/* Packs SCST LUN back to SCSI form */
+uint64_t scst_pack_lun(const uint64_t lun, unsigned int addr_method)
 {
-       uint64_t res;
+
+       uint64_t res = 0;
        uint16_t *p = (uint16_t *)&res;
 
        res = lun;
+
+       if ((addr_method == SCST_LUN_ADDR_METHOD_FLAT) && (lun != 0)) {
+               /*
+                * Flat space: luns other than 0 should use flat space
+                * addressing method.
+                */
+               *p = 0x7fff & *p;
+               *p = 0x4000 | *p;
+       }
+       /* Default is to use peripheral device addressing mode */
+
        *p = cpu_to_be16(*p);
 
        TRACE_EXIT_HRES((unsigned long)res);
index 8c7fa13..8e9a90e 100644 (file)
@@ -125,6 +125,10 @@ extern unsigned long scst_trace_flag;
 
 #define SCST_TGT_RETRY_TIMEOUT               (3/2*HZ)
 
+/* Definitions of symbolic constants for LUN addressing method */
+#define SCST_LUN_ADDR_METHOD_PERIPHERAL        0
+#define SCST_LUN_ADDR_METHOD_FLAT      1
+
 extern unsigned int scst_max_dev_cmd_mem;
 
 extern mempool_t *scst_mgmt_mempool;
@@ -417,7 +421,7 @@ int scst_alloc_space(struct scst_cmd *cmd);
 int scst_lib_init(void);
 void scst_lib_exit(void);
 
-uint64_t scst_pack_lun(const uint64_t lun);
+uint64_t scst_pack_lun(const uint64_t lun, unsigned int addr_method);
 uint64_t scst_unpack_lun(const uint8_t *lun, int len);
 
 struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask);
index 4b1f36a..7191427 100644 (file)
@@ -37,7 +37,7 @@
 static int scst_proc_init_groups(void);
 static void scst_proc_cleanup_groups(void);
 static int scst_proc_assign_handler(char *buf);
-static int scst_proc_group_add(const char *p);
+static int scst_proc_group_add(const char *p, unsigned int addr_method);
 static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc);
 
 static struct scst_proc_data scst_version_proc_data;
@@ -45,6 +45,7 @@ static struct scst_proc_data scst_help_proc_data;
 static struct scst_proc_data scst_sgv_proc_data;
 static struct scst_proc_data scst_groups_names_proc_data;
 static struct scst_proc_data scst_groups_devices_proc_data;
+static struct scst_proc_data scst_groups_addr_method_proc_data;
 static struct scst_proc_data scst_sessions_proc_data;
 static struct scst_proc_data scst_dev_handler_type_proc_data;
 static struct scst_proc_data scst_tgt_proc_data;
@@ -67,6 +68,7 @@ static struct scst_proc_data scst_dev_handler_proc_data;
 #define SCST_PROC_GROUPS_ENTRY_NAME            "groups"
 #define SCST_PROC_GROUPS_DEVICES_ENTRY_NAME    "devices"
 #define SCST_PROC_GROUPS_USERS_ENTRY_NAME      "names"
+#define SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME "addr_method"
 
 #ifdef CONFIG_SCST_MEASURE_LATENCY
 #define SCST_PROC_LAT_ENTRY_NAME               "latency"
@@ -127,7 +129,7 @@ static struct scst_trace_log scst_proc_local_trace_tbl[] = {
 static char *scst_proc_help_string =
 "   echo \"assign H:C:I:L HANDLER_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
 "\n"
-"   echo \"add_group GROUP_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
+"   echo \"add_group GROUP_NAME [FLAT]\" >/proc/scsi_tgt/scsi_tgt\n"
 "   echo \"del_group GROUP_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
 "   echo \"rename_group OLD_NAME NEW_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
 "\n"
@@ -811,17 +813,30 @@ static int scst_proc_group_add_tree(struct scst_acg *acg, const char *name)
                goto out;
        }
 
+       scst_groups_addr_method_proc_data.data = acg;
+       generic = scst_create_proc_entry(acg->acg_proc_root,
+                                SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME,
+                                &scst_groups_addr_method_proc_data);
+       if (!generic) {
+               PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
+                      SCST_PROC_ENTRY_NAME,
+                      SCST_PROC_GROUPS_ENTRY_NAME,
+                      name, SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME);
+               res = -ENOMEM;
+               goto out_remove;
+       }
+
        scst_groups_devices_proc_data.data = acg;
        generic = scst_create_proc_entry(acg->acg_proc_root,
                                         SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
                                         &scst_groups_devices_proc_data);
        if (!generic) {
-               PRINT_ERROR("cannot init /proc/%s/%s/%s/%s",
+               PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
                               SCST_PROC_ENTRY_NAME,
                               SCST_PROC_GROUPS_ENTRY_NAME,
                               name, SCST_PROC_GROUPS_DEVICES_ENTRY_NAME);
                res = -ENOMEM;
-               goto out_remove;
+               goto out_remove0;
        }
 
        scst_groups_names_proc_data.data = acg;
@@ -829,7 +844,7 @@ static int scst_proc_group_add_tree(struct scst_acg *acg, const char *name)
                                         SCST_PROC_GROUPS_USERS_ENTRY_NAME,
                                         &scst_groups_names_proc_data);
        if (!generic) {
-               PRINT_ERROR("cannot init /proc/%s/%s/%s/%s",
+               PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
                               SCST_PROC_ENTRY_NAME,
                               SCST_PROC_GROUPS_ENTRY_NAME,
                               name, SCST_PROC_GROUPS_USERS_ENTRY_NAME);
@@ -845,6 +860,9 @@ out_remove1:
        remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
                          acg->acg_proc_root);
 
+out_remove0:
+       remove_proc_entry(SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME,
+                         acg->acg_proc_root);
 out_remove:
        remove_proc_entry(name, scst_proc_groups_root);
        goto out;
@@ -855,9 +873,9 @@ static void scst_proc_del_acg_tree(struct proc_dir_entry *acg_proc_root,
 {
        TRACE_ENTRY();
 
+       remove_proc_entry(SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME, acg_proc_root);
        remove_proc_entry(SCST_PROC_GROUPS_USERS_ENTRY_NAME, acg_proc_root);
-       remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
-                               acg_proc_root);
+       remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME, acg_proc_root);
        remove_proc_entry(name, scst_proc_groups_root);
 
        TRACE_EXIT();
@@ -865,7 +883,7 @@ static void scst_proc_del_acg_tree(struct proc_dir_entry *acg_proc_root,
 }
 
 /* The activity supposed to be suspended and scst_mutex held */
-static int scst_proc_group_add(const char *p)
+static int scst_proc_group_add(const char *p, unsigned int addr_method)
 {
        int res = 0, len = strlen(p) + 1;
        struct scst_acg *acg;
@@ -886,6 +904,8 @@ static int scst_proc_group_add(const char *p)
                goto out_free;
        }
 
+       acg->addr_method = addr_method;
+
        res = scst_proc_group_add_tree(acg, p);
        if (res != 0)
                goto out_free_acg;
@@ -1536,8 +1556,9 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
                                        size_t length, loff_t *off)
 {
        int res, rc = 0, action;
-       char *buffer, *p, *pp;
+       char *buffer, *p, *pp, *ppp;
        struct scst_acg *a, *acg = NULL;
+       unsigned int addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
 
        TRACE_ENTRY();
 
@@ -1566,7 +1587,7 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
        }
 
        /*
-        * Usage: echo "add_group GROUP_NAME" >/proc/scsi_tgt/scsi_tgt
+        * Usage: echo "add_group GROUP_NAME [FLAT]" >/proc/scsi_tgt/scsi_tgt
         *   or   echo "del_group GROUP_NAME" >/proc/scsi_tgt/scsi_tgt
         *   or   echo "rename_group OLD_NAME NEW_NAME" >/proc/scsi_tgt/scsi_tgt"
         *   or   echo "assign H:C:I:L HANDLER_NAME" >/proc/scsi_tgt/scsi_tgt
@@ -1603,6 +1624,9 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
 
        res = length;
 
+       while (isspace(*p) && *p != '\0')
+               p++;
+
        switch (action) {
        case SCST_PROC_ACTION_ADD_GROUP:
        case SCST_PROC_ACTION_DEL_GROUP:
@@ -1618,6 +1642,29 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
                        if (*pp != '\0') {
                                switch (action) {
                                case SCST_PROC_ACTION_ADD_GROUP:
+                                       ppp = pp;
+                                       while (!isspace(*ppp) && *ppp != '\0')
+                                               ppp++;
+                                       if (*ppp != '\0') {
+                                               *ppp = '\0';
+                                          ppp++;
+                                          while (isspace(*ppp) && *ppp != '\0')
+                                               ppp++;
+                                          if (*ppp != '\0') {
+                                               PRINT_ERROR("%s", "Too many "
+                                                       "arguments");
+                                                       res = -EINVAL;
+                                                       goto out_up_free;
+                                          }
+                                       }
+                                       if (strcasecmp(pp, "FLAT") != 0) {
+                                               PRINT_ERROR("Unexpected "
+                                                       "argument %s", pp);
+                                               res = -EINVAL;
+                                               goto out_up_free;
+                                       } else
+                                               addr_method = SCST_LUN_ADDR_METHOD_FLAT;
+                                       break;
                                case SCST_PROC_ACTION_DEL_GROUP:
                                        PRINT_ERROR("%s", "Too many "
                                                "arguments");
@@ -1650,7 +1697,7 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
                                res = -EINVAL;
                                goto out_up_free;
                        }
-                       rc = scst_proc_group_add(p);
+                       rc = scst_proc_group_add(p, addr_method);
                        break;
                case SCST_PROC_ACTION_DEL_GROUP:
                        if (acg == NULL) {
@@ -2396,6 +2443,40 @@ static struct scst_proc_data scst_groups_names_proc_data = {
        .show = scst_groups_names_show,
 };
 
+static int scst_groups_addr_method_show(struct seq_file *seq, void *v)
+{
+       int res = 0;
+       struct scst_acg *acg = (struct scst_acg *)seq->private;
+
+       TRACE_ENTRY();
+
+       if (mutex_lock_interruptible(&scst_mutex) != 0) {
+               res = -EINTR;
+               goto out;
+       }
+
+       switch (acg->addr_method) {
+       case SCST_LUN_ADDR_METHOD_FLAT:
+               seq_printf(seq, "%s\n", "FLAT");
+               break;
+       case SCST_LUN_ADDR_METHOD_PERIPHERAL:
+               seq_printf(seq, "%s\n", "PERIPHERAL");
+               break;
+       default:
+               seq_printf(seq, "%s\n", "UNKNOWN");
+               break;
+       }
+
+       mutex_unlock(&scst_mutex);
+
+out:
+       TRACE_EXIT_RES(res);
+       return res;
+}
+static struct scst_proc_data scst_groups_addr_method_proc_data = {
+       SCST_DEF_RW_SEQ_OP(NULL)
+       .show = scst_groups_addr_method_show,
+};
 static int scst_groups_devices_show(struct seq_file *seq, void *v)
 {
        int res = 0;
index 28fa222..3872e6f 100644 (file)
@@ -106,6 +106,12 @@ static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
 static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
                                    struct kobj_attribute *attr,
                                    const char *buf, size_t count);
+static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  char *buf);
+static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t count);
 static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
                                   struct kobj_attribute *attr,
                                   char *buf);
@@ -127,6 +133,12 @@ static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
 static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
                                    struct kobj_attribute *attr,
                                    const char *buf, size_t count);
+static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  char *buf);
+static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t count);
 static ssize_t scst_acn_file_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf);
 
@@ -513,10 +525,18 @@ static struct kobj_attribute scst_ini_group_mgmt =
        __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_ini_group_mgmt_show,
               scst_ini_group_mgmt_store);
 
+static struct kobj_attribute scst_tgt_addr_method =
+       __ATTR(addr_method, S_IRUGO | S_IWUSR, scst_tgt_addr_method_show,
+              scst_tgt_addr_method_store);
+
 static struct kobj_attribute scst_rel_tgt_id =
        __ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show,
               scst_rel_tgt_id_store);
 
+static struct kobj_attribute scst_acg_addr_method =
+       __ATTR(addr_method, S_IRUGO | S_IWUSR, scst_acg_addr_method_show,
+               scst_acg_addr_method_store);
+
 static ssize_t scst_tgt_enable_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf)
 {
@@ -672,6 +692,14 @@ int scst_create_tgt_sysfs(struct scst_tgt *tgt)
                goto out;
        }
 
+       retval = sysfs_create_file(&tgt->tgt_kobj,
+                       &scst_tgt_addr_method.attr);
+       if (retval != 0) {
+               PRINT_ERROR("Can't add attribute %s for tgt %s",
+                       scst_tgt_addr_method.attr.name, tgt->tgt_name);
+               goto out;
+       }
+
        pattr = tgt->tgtt->tgt_attrs;
        if (pattr != NULL) {
                while (*pattr != NULL) {
@@ -1652,12 +1680,76 @@ static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
 
        tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
        acg = tgt->default_acg;
+
        res = __scst_luns_mgmt_store(acg, kobj, buf, count);
 
        TRACE_EXIT_RES(res);
        return res;
 }
 
+static ssize_t __scst_acg_addr_method_show(struct scst_acg *acg, char *buf)
+{
+       int res;
+
+       switch (acg->addr_method) {
+       case SCST_LUN_ADDR_METHOD_FLAT:
+               res = sprintf(buf, "FLAT\n%s\n", SCST_SYSFS_KEY_MARK);
+               break;
+       case SCST_LUN_ADDR_METHOD_PERIPHERAL:
+               res = sprintf(buf, "PERIPHERAL\n");
+               break;
+       default:
+               res = sprintf(buf, "UNKNOWN\n");
+               break;
+       }
+
+       return res;
+}
+
+static ssize_t __scst_acg_addr_method_store(struct scst_acg *acg,
+       const char *buf, size_t count)
+{
+       int res = count;
+
+       if (strncasecmp(buf, "FLAT", min_t(int, 4, count)) == 0)
+               acg->addr_method = SCST_LUN_ADDR_METHOD_FLAT;
+       else if (strncasecmp(buf, "PERIPHERAL", min_t(int, 10, count)) == 0)
+               acg->addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
+       else {
+               PRINT_ERROR("Unknown address method %s", buf);
+               res = -EINVAL;
+       }
+       return res;
+}
+
+static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
+       struct kobj_attribute *attr, char *buf)
+{
+       struct scst_acg *acg;
+       struct scst_tgt *tgt;
+
+       tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
+       acg = tgt->default_acg;
+
+       return __scst_acg_addr_method_show(acg, buf);
+}
+
+static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
+       struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int res;
+       struct scst_acg *acg;
+       struct scst_tgt *tgt;
+
+       tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
+       acg = tgt->default_acg;
+
+       res = __scst_acg_addr_method_store(acg, buf, count);
+
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
 static int scst_create_acg_sysfs(struct scst_tgt *tgt,
        struct scst_acg *acg)
 {
@@ -1705,6 +1797,14 @@ static int scst_create_acg_sysfs(struct scst_tgt *tgt,
                        scst_acg_ini_mgmt.attr.name, tgt->tgt_name);
                goto out;
        }
+
+       retval = sysfs_create_file(&acg->acg_kobj, &scst_acg_addr_method.attr);
+       if (retval != 0) {
+               PRINT_ERROR("Can't add tgt attr %s for tgt %s",
+                       scst_acg_addr_method.attr.name,
+                               tgt->tgt_name);
+               goto out;
+       }
 out:
        TRACE_EXIT_RES(retval);
        return retval;
@@ -1732,13 +1832,35 @@ void scst_acg_sysfs_put(struct scst_acg *acg)
        return;
 }
 
+static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
+       struct kobj_attribute *attr, char *buf)
+{
+       struct scst_acg *acg;
+
+       acg = container_of(kobj, struct scst_acg, acg_kobj);
+
+       return __scst_acg_addr_method_show(acg, buf);
+}
+
+static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
+       struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int res;
+       struct scst_acg *acg;
+
+       acg = container_of(kobj, struct scst_acg, acg_kobj);
+
+       res = __scst_acg_addr_method_store(acg, buf, count);
+
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
 static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf)
 {
-       static char *help = "Usage: echo \"create GROUP_NAME\" "
-                                       ">mgmt\n"
-                           "       echo \"del GROUP_NAME\" "
-                                       ">mgmt\n";
+       static char *help = "Usage: echo \"create GROUP_NAME\" >mgmt\n"
+                           "       echo \"del GROUP_NAME\" >mgmt\n";
 
        return sprintf(buf, help);
 }
index be02313..a8d65f8 100644 (file)
@@ -1481,8 +1481,15 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
                                                buffer_size);
                                        goto out_put_hw_err;
                                }
-                               buffer[offs] = (tgt_dev->lun >> 8) & 0xff;
-                               buffer[offs+1] = tgt_dev->lun & 0xff;
+                               if ((cmd->sess->acg->addr_method == SCST_LUN_ADDR_METHOD_FLAT) &&
+                                   (tgt_dev->lun != 0)) {
+                                       buffer[offs] = (tgt_dev->lun >> 8) & 0x3f;
+                                       buffer[offs] = buffer[offs] | 0x40;
+                                       buffer[offs+1] = tgt_dev->lun & 0xff;
+                               } else {
+                                       buffer[offs] = (tgt_dev->lun >> 8) & 0xff;
+                                       buffer[offs+1] = tgt_dev->lun & 0xff;
+                               }
                                offs += 8;
                        }
 inc_dev_cnt: