Avoid that enabling a target too quickly triggers a crash (merge r4515 from trunk)

git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.2.x@6079 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2015-02-11 09:01:54 +00:00
parent 74c2750e5a
commit de833ce16d
6 changed files with 98 additions and 26 deletions

View File

@@ -614,7 +614,7 @@ int ft_tgt_enable(struct scst_tgt *tgt, bool enable)
FT_SESS_DBG("enable tgt %s\n", tgt->tgt_name);
tport = scst_tgt_get_tgt_priv(tgt);
if (tport == NULL) {
ret = -EBUSY;
ret = -E_TGT_PRIV_NOT_YET_SET;
goto out_unlock;
}
tport->enabled = 1;

View File

@@ -454,19 +454,22 @@ const struct seq_operations iscsi_seq_op = {
static ssize_t iscsi_tgt_tid_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
int pos;
int res = -E_TGT_PRIV_NOT_YET_SET;
struct scst_tgt *scst_tgt;
struct iscsi_target *tgt;
TRACE_ENTRY();
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
pos = sprintf(buf, "%u\n", tgt->tid);
res = sprintf(buf, "%u\n", tgt->tid);
TRACE_EXIT_RES(pos);
return pos;
out:
TRACE_EXIT_RES(res);
return res;
}
static struct kobj_attribute iscsi_tgt_attr_tid =
@@ -532,6 +535,11 @@ int iscsi_enable_target(struct scst_tgt *scst_tgt, bool enable)
TRACE_ENTRY();
if (tgt == NULL) {
res = -E_TGT_PRIV_NOT_YET_SET;
goto out;
}
if (enable)
type = E_ENABLE_TARGET;
else
@@ -541,6 +549,7 @@ int iscsi_enable_target(struct scst_tgt *scst_tgt, bool enable)
res = iscsi_sysfs_send_event(tgt->tid, type, NULL, NULL, NULL);
out:
TRACE_EXIT_RES(res);
return res;
}
@@ -550,7 +559,10 @@ bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt)
struct iscsi_target *tgt =
(struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
return tgt->tgt_enabled;
if (tgt != NULL)
return tgt->tgt_enabled;
else
return false;
}
ssize_t iscsi_sysfs_add_target(const char *target_name, char *params)

View File

@@ -6090,23 +6090,31 @@ out:
static int q2t_enable_tgt(struct scst_tgt *scst_tgt, bool enable)
{
struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
scsi_qla_host_t *ha = tgt->ha;
int res;
scsi_qla_host_t *ha;
int res = -E_TGT_PRIV_NOT_YET_SET;
if (tgt == NULL)
goto out;
ha = tgt->ha;
if (enable)
res = q2t_host_action(ha, ENABLE_TARGET_MODE);
else
res = q2t_host_action(ha, DISABLE_TARGET_MODE);
out:
return res;
}
static bool q2t_is_tgt_enabled(struct scst_tgt *scst_tgt)
{
struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
scsi_qla_host_t *ha = tgt->ha;
return qla_tgt_mode_enabled(ha);
if (tgt == NULL)
return false;
return qla_tgt_mode_enabled(tgt->ha);
}
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) || \
@@ -6314,16 +6322,19 @@ static ssize_t q2t_show_expl_conf_enabled(struct kobject *kobj,
struct scst_tgt *scst_tgt;
struct q2t_tgt *tgt;
scsi_qla_host_t *ha;
ssize_t size;
int res = -E_TGT_PRIV_NOT_YET_SET;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
ha = tgt->ha;
size = scnprintf(buffer, PAGE_SIZE, "%d\n%s", ha->enable_explicit_conf,
res = scnprintf(buffer, PAGE_SIZE, "%d\n%s", ha->enable_explicit_conf,
ha->enable_explicit_conf ? SCST_SYSFS_KEY_MARK "\n" : "");
return size;
out:
return res;
}
static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
@@ -6332,10 +6343,13 @@ static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
struct scst_tgt *scst_tgt;
struct q2t_tgt *tgt;
scsi_qla_host_t *ha, *pha;
int res = -E_TGT_PRIV_NOT_YET_SET;
unsigned long flags;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
ha = tgt->ha;
pha = to_qla_parent(ha);
@@ -6360,7 +6374,10 @@ static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
spin_unlock_irqrestore(&pha->hardware_lock, flags);
return size;
res = size;
out:
return res;
}
static ssize_t q2t_abort_isp_store(struct kobject *kobj,
@@ -6369,9 +6386,12 @@ static ssize_t q2t_abort_isp_store(struct kobject *kobj,
struct scst_tgt *scst_tgt;
struct q2t_tgt *tgt;
scsi_qla_host_t *ha;
int res = -E_TGT_PRIV_NOT_YET_SET;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
ha = tgt->ha;
PRINT_INFO("qla2x00t(%ld): Aborting ISP", ha->instance);
@@ -6379,7 +6399,10 @@ static ssize_t q2t_abort_isp_store(struct kobject *kobj,
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
qla2x00_wait_for_hba_online(ha);
return size;
res = size;
out:
return res;
}
static ssize_t q2t_version_show(struct kobject *kobj,
@@ -6419,12 +6442,14 @@ static ssize_t q2t_node_name_show(struct kobject *kobj,
struct scst_tgt *scst_tgt;
struct q2t_tgt *tgt;
scsi_qla_host_t *ha;
ssize_t res;
ssize_t res = -E_TGT_PRIV_NOT_YET_SET;
char *wwn;
uint8_t *node_name;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
ha = tgt->ha;
if (ha->parent == NULL) {
@@ -6456,12 +6481,14 @@ static ssize_t q2t_node_name_store(struct kobject *kobj,
struct q2t_tgt *tgt;
scsi_qla_host_t *ha;
u64 node_name, old_node_name;
int res;
int res = -E_TGT_PRIV_NOT_YET_SET;
TRACE_ENTRY();
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
ha = tgt->ha;
sBUG_ON(ha->parent != NULL);
@@ -6508,11 +6535,13 @@ static ssize_t q2t_vp_parent_host_show(struct kobject *kobj,
struct scst_tgt *scst_tgt;
struct q2t_tgt *tgt;
scsi_qla_host_t *ha;
ssize_t res;
ssize_t res = -E_TGT_PRIV_NOT_YET_SET;
char *wwn;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
goto out;
ha = to_qla_parent(tgt->ha);
res = q2t_get_target_name(ha->port_name, &wwn);

View File

@@ -31,6 +31,10 @@
#endif
#include <scsi/scsi.h>
#ifndef __KERNEL__
#include <errno.h>
#endif
/*
* Version numbers, the same as for the kernel.
*
@@ -519,4 +523,13 @@ enum scst_tg_sup {
#define SCST_MIN_REL_TGT_ID 1
#define SCST_MAX_REL_TGT_ID 65535
/*
* Error code returned by target attribute sysfs methods if invoked after
* scst_register_target() finished but before before scst_tgt_set_tgt_priv()
* has been invoked.
*/
enum {
E_TGT_PRIV_NOT_YET_SET = EBUSY
};
#endif /* __SCST_CONST_H */

View File

@@ -408,6 +408,8 @@ static ssize_t scst_local_scsi_transport_version_show(struct kobject *kobj,
if (down_read_trylock(&scst_local_exit_rwsem) == 0)
goto out;
res = -E_TGT_PRIV_NOT_YET_SET;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
@@ -436,6 +438,8 @@ static ssize_t scst_local_scsi_transport_version_store(struct kobject *kobj,
if (down_read_trylock(&scst_local_exit_rwsem) == 0)
goto out;
res = -E_TGT_PRIV_NOT_YET_SET;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
@@ -476,6 +480,8 @@ static ssize_t scst_local_phys_transport_version_show(struct kobject *kobj,
if (down_read_trylock(&scst_local_exit_rwsem) == 0)
goto out;
res = -E_TGT_PRIV_NOT_YET_SET;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
@@ -502,6 +508,8 @@ static ssize_t scst_local_phys_transport_version_store(struct kobject *kobj,
if (down_read_trylock(&scst_local_exit_rwsem) == 0)
goto out;
res = -E_TGT_PRIV_NOT_YET_SET;
scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
tgt = scst_tgt_get_tgt_priv(scst_tgt);
if (!tgt)
@@ -1547,6 +1555,11 @@ static uint16_t scst_local_get_scsi_transport_version(struct scst_tgt *scst_tgt)
{
struct scst_local_tgt *tgt = scst_tgt_get_tgt_priv(scst_tgt);
/*
* It's OK to not check tgt != NULL here, because new sessions
* can't create before its' set.
*/
if (tgt->scsi_transport_version == 0)
return 0x0BE0; /* SAS */
else
@@ -1557,6 +1570,11 @@ static uint16_t scst_local_get_phys_transport_version(struct scst_tgt *scst_tgt)
{
struct scst_local_tgt *tgt = scst_tgt_get_tgt_priv(scst_tgt);
/*
* It's OK to not check tgt != NULL here, because new sessions
* can't create before its' set.
*/
return tgt->phys_transport_version;
}

View File

@@ -2333,7 +2333,7 @@ static int srpt_enable_target(struct scst_tgt *scst_tgt, bool enable)
EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
if (!sdev)
return -ENOENT;
return -E_TGT_PRIV_NOT_YET_SET;
TRACE_DBG("%s target %s", enable ? "Enabling" : "Disabling",
sdev->device->name);