mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-18 03:01:26 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user