Patch from Alexey Obitotskiy <alexeyo1@open-e.com> with cleanups and fixes implementing setting and managing relative target IDs.

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1523 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-03-01 13:38:06 +00:00
parent 5d2da8b297
commit 5f973827df
6 changed files with 207 additions and 23 deletions

View 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

View 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 */

View 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)

View 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);

View 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);

View 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;