Patch from Alexey Obitotskiy <alexeyo1@open-e.com> with cleanups and fixes implementi...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 1 Mar 2010 13:38:06 +0000 (13:38 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 1 Mar 2010 13:38:06 +0000 (13:38 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1523 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/include/scst.h
scst/include/scst_const.h
scst/src/scst_lib.c
scst/src/scst_main.c
scst/src/scst_priv.h
scst/src/scst_sysfs.c

index f7991d7..77ab2e0 100644 (file)
@@ -1180,8 +1180,10 @@ struct scst_tgt {
        /* Name of the target */
        char *tgt_name;
 
+       uint16_t rel_tgt_id;
+
 #ifdef CONFIG_SCST_PROC
-       /* Name on the default security group ("Default_target_name") */
+       /* Name of the default security group ("Default_target_name") */
        char *default_group_name;
 #endif
 
index 636afd3..3f79e79 100644 (file)
@@ -355,4 +355,7 @@ enum scst_cdb_flags {
 
 #define SCST_SYSFS_KEY_MARK    "[key]"
 
+#define SCST_MIN_REL_TGT_ID                    1
+#define SCST_MAX_REL_TGT_ID                    65535
+
 #endif /* __SCST_CONST_H */
index fb7739b..25af9e2 100644 (file)
@@ -1881,32 +1881,96 @@ restart:
        return;
 }
 
-struct scst_tgt *scst_alloc_tgt(struct scst_tgt_template *tgtt)
+bool scst_is_relative_target_port_id_unique(uint16_t id, struct scst_tgt *t)
 {
-       struct scst_tgt *tgt;
+       bool res = true;
+       struct scst_tgt_template *tgtt;
 
        TRACE_ENTRY();
 
-       tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
-       if (tgt == NULL) {
+       mutex_lock(&scst_mutex);
+       list_for_each_entry(tgtt, &scst_template_list,
+                               scst_template_list_entry) {
+               struct scst_tgt *tgt;
+               list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
+                       if (tgt == t)
+                               continue;
+                       if (id == tgt->rel_tgt_id) {
+                               res = false;
+                               break;
+                       }
+               }
+       }
+       mutex_unlock(&scst_mutex);
+
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
+int gen_relative_target_port_id(uint16_t *id)
+{
+       int res = -EOVERFLOW;
+       static unsigned long rti = SCST_MIN_REL_TGT_ID, rti_prev;
+
+       TRACE_ENTRY();
+
+       rti_prev = rti;
+       do {
+               if (scst_is_relative_target_port_id_unique(rti, NULL)) {
+                       *id = (uint16_t)rti++;
+                       res = 0;
+                       goto out;
+               }
+               rti++;
+               if (rti > SCST_MAX_REL_TGT_ID)
+                       rti = SCST_MIN_REL_TGT_ID;
+       } while (rti != rti_prev);
+
+       PRINT_ERROR("%s", "Unable to create unique relative target port id");
+
+out:
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
+int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt)
+{
+       struct scst_tgt *t;
+       int res = 0;
+
+       TRACE_ENTRY();
+
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (t == NULL) {
                TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of tgt failed");
+               res = -ENOMEM;
                goto out;
        }
 
-       INIT_LIST_HEAD(&tgt->sess_list);
-       init_waitqueue_head(&tgt->unreg_waitQ);
-       tgt->tgtt = tgtt;
-       tgt->sg_tablesize = tgtt->sg_tablesize;
-       spin_lock_init(&tgt->tgt_lock);
-       INIT_LIST_HEAD(&tgt->retry_cmd_list);
-       atomic_set(&tgt->finished_cmds, 0);
-       init_timer(&tgt->retry_timer);
-       tgt->retry_timer.data = (unsigned long)tgt;
-       tgt->retry_timer.function = scst_tgt_retry_timer_fn;
+       INIT_LIST_HEAD(&t->sess_list);
+       init_waitqueue_head(&t->unreg_waitQ);
+       t->tgtt = tgtt;
+       t->sg_tablesize = tgtt->sg_tablesize;
+       spin_lock_init(&t->tgt_lock);
+       INIT_LIST_HEAD(&t->retry_cmd_list);
+       atomic_set(&t->finished_cmds, 0);
+       init_timer(&t->retry_timer);
+       t->retry_timer.data = (unsigned long)t;
+       t->retry_timer.function = scst_tgt_retry_timer_fn;
+
+#ifdef CONFIG_SCST_PROC
+       res = gen_relative_target_port_id(&t->rel_tgt_id);
+       if (res != 0) {
+               scst_free_tgt(t);
+               goto out;
+       }
+#endif
+
+       *tgt = t;
 
 out:
-       TRACE_EXIT_HRES((unsigned long)tgt);
-       return tgt;
+       TRACE_EXIT_HRES(res);
+       return res;
 }
 
 void scst_free_tgt(struct scst_tgt *tgt)
index e5ad825..9f2295c 100644 (file)
@@ -361,11 +361,9 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
 
        TRACE_ENTRY();
 
-       tgt = scst_alloc_tgt(vtt);
-       if (tgt == NULL) {
-               rc = -ENOMEM;
+       rc = scst_alloc_tgt(vtt, &tgt);
+       if (rc != 0)
                goto out_err;
-       }
 
        rc = scst_suspend_activity(true);
        if (rc != 0)
@@ -449,8 +447,13 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
        mutex_unlock(&scst_mutex);
        scst_resume_activity();
 
+#ifdef CONFIG_SCST_PROC
+       PRINT_INFO("Target %s (rel ID %d) for template %s registered successfully",
+               tgt->tgt_name, tgt->rel_tgt_id, vtt->name);
+#else
        PRINT_INFO("Target %s for template %s registered successfully",
                tgt->tgt_name, vtt->name);
+#endif
 
        TRACE_DBG("tgt %p", tgt);
 
index c5e7ece..7351587 100644 (file)
@@ -296,7 +296,7 @@ int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds);
 static inline void scst_tgtt_cleanup(struct scst_tgt_template *tgtt) { }
 static inline void scst_devt_cleanup(struct scst_dev_type *devt) { }
 
-struct scst_tgt *scst_alloc_tgt(struct scst_tgt_template *tgtt);
+int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt);
 void scst_free_tgt(struct scst_tgt *tgt);
 
 int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev);
@@ -735,6 +735,9 @@ static inline int scst_sn_before(__u32 seq1, __u32 seq2)
        return (__s32)(seq1-seq2) < 0;
 }
 
+bool scst_is_relative_target_port_id_unique(uint16_t id, struct scst_tgt *t);
+int gen_relative_target_port_id(uint16_t *id);
+
 #ifdef CONFIG_SCST_MEASURE_LATENCY
 
 void scst_set_start_time(struct scst_cmd *cmd);
index f892dfa..f035440 100644 (file)
@@ -112,6 +112,12 @@ static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
 static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
                                    struct kobj_attribute *attr,
                                    const char *buf, size_t count);
+static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  char *buf);
+static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t count);
 static ssize_t scst_acg_luns_mgmt_show(struct kobject *kobj,
                                   struct kobj_attribute *attr,
                                   char *buf);
@@ -526,6 +532,10 @@ 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_rel_tgt_id =
+       __ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show,
+              scst_rel_tgt_id_store);
+
 static ssize_t scst_tgt_enable_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf)
 {
@@ -558,6 +568,23 @@ static ssize_t scst_tgt_enable_store(struct kobject *kobj,
 
        tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
 
+       if (buf[0] == '1') {
+               if (tgt->rel_tgt_id == 0) {
+                       res = gen_relative_target_port_id(&tgt->rel_tgt_id);
+                       if (res)
+                               goto out;
+                       PRINT_INFO("Using autogenerated rel ID %d for target "
+                               "%s", tgt->rel_tgt_id, tgt->tgt_name);
+               } else
+                       if (!scst_is_relative_target_port_id_unique(
+                           tgt->rel_tgt_id, tgt)) {
+                               PRINT_ERROR("Relative port id %d is not unique",
+                                       tgt->rel_tgt_id);
+                                       res = -EBADSLT;
+                               goto out;
+                       }
+       }
+
        res = tgt->tgtt->enable_target(tgt, buf, count);
        if (res == 0)
                res = count;
@@ -638,13 +665,21 @@ int scst_create_tgt_sysfs(struct scst_tgt *tgt)
        }
 
        retval = sysfs_create_file(tgt->tgt_ini_grp_kobj,
-               &scst_ini_group_mgmt.attr);
+                       &scst_ini_group_mgmt.attr);
        if (retval != 0) {
                PRINT_ERROR("Can't add tgt attr %s for tgt %s",
                        scst_ini_group_mgmt.attr.name, tgt->tgt_name);
                goto out;
        }
 
+       retval = sysfs_create_file(&tgt->tgt_kobj,
+                       &scst_rel_tgt_id.attr);
+       if (retval != 0) {
+               PRINT_ERROR("Can't add attribute %s for tgt %s",
+                       scst_rel_tgt_id.attr.name, tgt->tgt_name);
+               goto out;
+       }
+
        pattr = tgt->tgtt->tgt_attrs;
        if (pattr != NULL) {
                while (*pattr != NULL) {
@@ -1797,6 +1832,80 @@ out_free_acg:
 #undef SCST_LUN_ACTION_DEL
 }
 
+static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
+       struct kobj_attribute *attr, char *buf)
+{
+       struct scst_tgt *tgt;
+       int res;
+
+       TRACE_ENTRY();
+
+       tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
+
+       res = sprintf(buf, "%d\n%s", tgt->rel_tgt_id,
+               (tgt->rel_tgt_id != 0) ? SCST_SYSFS_KEY_MARK "\n" : "");
+
+       TRACE_EXIT_RES(res);
+       return res;
+}
+
+static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
+       struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int res = 0;
+       struct scst_tgt *tgt;
+       unsigned long rel_tgt_id;
+
+       TRACE_ENTRY();
+
+       if (buf == NULL)
+               goto out_err;
+
+       tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
+
+       res = strict_strtoul(buf, 0, &rel_tgt_id);
+       if (res != 0)
+               goto out_err;
+
+       TRACE_DBG("Try to set relative target port id %d",
+               (uint16_t)rel_tgt_id);
+
+       if (rel_tgt_id < SCST_MIN_REL_TGT_ID ||
+           rel_tgt_id > SCST_MAX_REL_TGT_ID) {
+               if ((rel_tgt_id == 0) && !tgt->tgtt->is_target_enabled(tgt))
+                       goto set;
+
+               PRINT_ERROR("Invalid relative port id %d",
+                       (uint16_t)rel_tgt_id);
+               res = -EINVAL;
+               goto out;
+       }
+
+       if (tgt->tgtt->is_target_enabled(tgt) &&
+           rel_tgt_id != tgt->rel_tgt_id) {
+               if (!scst_is_relative_target_port_id_unique(rel_tgt_id, tgt)) {
+                       PRINT_ERROR("Relative port id %d is not unique",
+                               (uint16_t)rel_tgt_id);
+                       res = -EBADSLT;
+                       goto out;
+               }
+       }
+
+set:
+       tgt->rel_tgt_id = (uint16_t)rel_tgt_id;
+
+       res = count;
+
+out:
+       TRACE_EXIT_RES(res);
+       return res;
+
+out_err:
+       PRINT_ERROR("%s: Requested action not understood: %s", __func__, buf);
+       res = -EINVAL;
+       goto out;
+}
+
 int scst_create_acn_sysfs(struct scst_acg *acg, struct scst_acn *acn)
 {
        int retval = 0;