Make it possible to forcibly close SRP and FC sessions via sysfs

That patch contains the following changes:
* Move the code for creating a "close_sess" sysfs attribute from iscsi-scst to
  the SCST core such that it becomes available for other target drivers. This
  does not change the functionality of iscsi-scst.
* Add code in ib_srpt and qla2x00t to allow a session to be forcibly closed from
  user space.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>




git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4852 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2013-05-18 00:52:46 +00:00
parent 90222db2ac
commit 2093dd7561
6 changed files with 89 additions and 31 deletions

View File

@@ -3822,6 +3822,24 @@ out_err:
return;
}
static int iscsi_close_sess(struct scst_session *scst_sess)
{
struct iscsi_session *sess = scst_sess_get_tgt_priv(scst_sess);
struct iscsi_target *target = sess->target;
int res;
res = mutex_lock_interruptible(&target->target_mutex);
if (res)
goto out;
iscsi_sess_force_close(sess);
mutex_unlock(&target->target_mutex);
res = 0;
out:
return res;
}
static int iscsi_target_detect(struct scst_tgt_template *templ)
{
/* Nothing to do */
@@ -3869,6 +3887,7 @@ struct scst_tgt_template iscsi_template = {
.add_target = iscsi_sysfs_add_target,
.del_target = iscsi_sysfs_del_target,
.mgmt_cmd = iscsi_sysfs_mgmt_cmd,
.close_session = iscsi_close_sess,
.tgtt_optional_attributes = "IncomingUser, OutgoingUser",
.tgt_optional_attributes = "IncomingUser, OutgoingUser, allowed_portal",
#endif

View File

@@ -540,36 +540,6 @@ static ssize_t iscsi_sess_reinstating_show(struct kobject *kobj,
static struct kobj_attribute iscsi_sess_attr_reinstating =
__ATTR(reinstating, S_IRUGO, iscsi_sess_reinstating_show, NULL);
static ssize_t iscsi_sess_force_close_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
int res;
struct scst_session *scst_sess;
struct iscsi_session *sess;
TRACE_ENTRY();
scst_sess = container_of(kobj, struct scst_session, sess_kobj);
sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
res = mutex_lock_interruptible(&sess->target->target_mutex);
if (res != 0)
goto out;
iscsi_sess_force_close(sess);
mutex_unlock(&sess->target->target_mutex);
res = count;
out:
TRACE_EXIT_RES(res);
return res;
}
static struct kobj_attribute iscsi_sess_attr_force_close =
__ATTR(force_close, S_IWUSR, NULL, iscsi_sess_force_close_store);
const struct attribute *iscsi_sess_attrs[] = {
&iscsi_sess_attr_initial_r2t.attr,
&iscsi_sess_attr_immediate_data.attr,
@@ -582,7 +552,6 @@ const struct attribute *iscsi_sess_attrs[] = {
&iscsi_sess_attr_data_digest.attr,
&iscsi_attr_sess_sid.attr,
&iscsi_sess_attr_reinstating.attr,
&iscsi_sess_attr_force_close.attr,
NULL,
};

View File

@@ -102,6 +102,7 @@ static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset);
static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only);
static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd);
static int q2t_unreg_sess(struct q2t_sess *sess);
static int q2t_close_session(struct scst_session *scst_sess);
static uint16_t q2t_get_scsi_transport_version(struct scst_tgt *scst_tgt);
static uint16_t q2t_get_phys_transport_version(struct scst_tgt *scst_tgt);
@@ -219,6 +220,7 @@ static struct scst_tgt_template tgt2x_template = {
.rdy_to_xfer = q2t_rdy_to_xfer,
.on_free_cmd = q2t_on_free_cmd,
.task_mgmt_fn_done = q2t_task_mgmt_fn_done,
.close_session = q2t_close_session,
.get_initiator_port_transport_id = q2t_get_initiator_port_transport_id,
.get_scsi_transport_version = q2t_get_scsi_transport_version,
.get_phys_transport_version = q2t_get_phys_transport_version,
@@ -796,6 +798,20 @@ out:
return;
}
static int q2t_close_session(struct scst_session *scst_sess)
{
struct q2t_sess *sess = scst_sess_get_tgt_priv(scst_sess);
scsi_qla_host_t *ha = sess->tgt->ha;
scsi_qla_host_t *pha = to_qla_parent(ha);
unsigned long flags;
spin_lock_irqsave(&pha->hardware_lock, flags);
q2t_schedule_sess_for_deletion(sess);
spin_unlock_irqrestore(&pha->hardware_lock, flags);
return 0;
}
/* pha->hardware_lock supposed to be held on entry */
static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only)
{

View File

@@ -997,6 +997,19 @@ struct scst_tgt_template {
*/
ssize_t (*mgmt_cmd) (char *cmd);
/*
* Forcibly close a session. Note: this function may operate
* asynchronously - there is no guarantee the session will actually
* have been closed at the time this function returns. May be called
* with scst_mutex held. Activity may be suspended while this function
* is invoked. May sleep but must not wait until session
* unregistration finished. Must return 0 upon success and -EINTR if
* the session has not been closed because a signal has been received.
*
* OPTIONAL
*/
int (*close_session)(struct scst_session *sess);
/*
* Should return physical transport version. Used in the corresponding
* INQUIRY version descriptor. See SPC for the list of available codes.

View File

@@ -3553,6 +3553,28 @@ SCST_SESS_SYSFS_STAT_ATTR(cmd_count, bidi_cmd_count, SCST_DATA_BIDI, 0);
SCST_SESS_SYSFS_STAT_ATTR(io_byte_count, bidi_io_count_kb, SCST_DATA_BIDI, 1);
SCST_SESS_SYSFS_STAT_ATTR(cmd_count, none_cmd_count, SCST_DATA_NONE, 0);
static ssize_t scst_sess_force_close_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct scst_session *sess = container_of(kobj, struct scst_session,
sess_kobj);
int res;
res = sess->tgt->tgtt->close_session(sess);
if (res < 0)
goto out;
res = count;
out:
return res;
}
static struct kobj_attribute session_force_close_attr =
__ATTR(force_close, S_IWUSR, NULL, scst_sess_force_close_store);
static struct attribute *scst_session_attrs[] = {
&session_commands_attr.attr,
&session_active_commands_attr.attr,
@@ -3640,6 +3662,16 @@ int scst_sess_sysfs_create(struct scst_session *sess)
sess->sess_kobj_ready = 1;
if (sess->tgt->tgtt->close_session) {
res = sysfs_create_file(&sess->sess_kobj,
&session_force_close_attr.attr);
if (res != 0) {
PRINT_ERROR("Adding force_close sysfs attribute to session %s failed (%d)",
name, res);
goto out_del;
}
}
if (sess->tgt->tgtt->sess_attrs) {
res = sysfs_create_files(&sess->sess_kobj,
sess->tgt->tgtt->sess_attrs);

View File

@@ -3528,6 +3528,14 @@ static int srpt_detect(struct scst_tgt_template *tp)
return device_count;
}
static int srpt_close_session(struct scst_session *sess)
{
struct srpt_rdma_ch *ch = scst_sess_get_tgt_priv(sess);
srpt_close_ch(ch);
return 0;
}
static int srpt_ch_list_empty(struct srpt_tgt *srpt_tgt)
{
int res;
@@ -3752,6 +3760,7 @@ static struct scst_tgt_template srpt_template = {
.on_hw_pending_cmd_timeout = srpt_pending_cmd_timeout,
.on_free_cmd = srpt_on_free_cmd,
.task_mgmt_fn_done = srpt_tsk_mgmt_done,
.close_session = srpt_close_session,
.get_initiator_port_transport_id = srpt_get_initiator_port_transport_id,
.get_scsi_transport_version = srpt_get_scsi_transport_version,
};