Files
scst/iscsi-scst/kernel/session.c
T
Vladislav Bolkhovitin bb4d276a54 Merged revisions 7096,7101,7104,7106-7111,7115-7118,7125,7134-7137,7139,7141,7143,7152-7154,7158,7162-7163,7168-7171,7173,7175-7179,7185,7190,7193,7203,7208 via svnmerge from
svn+ssh://svn.code.sf.net/p/scst/svn/trunk

........
  r7096 | bvassche | 2017-02-23 18:08:17 -0800 (Thu, 23 Feb 2017) | 4 lines
  
  scst_copy_mgr: Avoid that LUN removal triggers a BUG()
  
  Reported-by: Jinpu Wang <jinpu.wang@profitbricks.com>
........
  r7101 | bvassche | 2017-03-01 07:31:59 -0800 (Wed, 01 Mar 2017) | 20 lines
  
  scst_vdisk: Avoid that LUN refresh triggers a general protection fault
  
  Avoid that triggering LUN referesh concurrently with device deletion
  triggers the following:
  
  general protection fault: 0000 [#1]
  Workqueue: events vdev_inq_changed_fn [scst_vdisk]
  Call Trace:
   _raw_spin_lock_bh+0x2b/0x30
   scst_cm_update_dev+0x87/0x190 [scst]
   scst_dev_inquiry_data_changed+0xfb/0x1b0 [scst]
   vdev_inq_changed_fn+0x60/0x120 [scst_vdisk]
   process_one_work+0x14d/0x410
   worker_thread+0x66/0x460
   kthread+0xdb/0x100
   ret_from_fork+0x3f/0x70
  
  Reported-by: Jinpu Wang <jinpu.wang@profitbricks.com>
  Tested-by: Jinpu Wang <jinpu.wang@profitbricks.com>
........
  r7104 | vlnb | 2017-03-07 20:36:45 -0800 (Tue, 07 Mar 2017) | 5 lines
  
  Linux kernel v4.10 build fix.
  
  Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
........
  r7106 | bvassche | 2017-04-11 11:48:36 -0700 (Tue, 11 Apr 2017) | 4 lines
  
  ib_srpt: Ensure that the BUG_ON() argument has no side effects
  
  Reported-by: David Butterfield <dab21774@gmail.com>
........
  r7107 | vlnb | 2017-04-13 15:04:07 -0700 (Thu, 13 Apr 2017) | 7 lines
  
  The argument to sleep() would get "promoted" to an integer with value zero.
  -               sleep(0.1);
  +               usleep(100*1000);
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7108 | vlnb | 2017-04-13 15:30:25 -0700 (Thu, 13 Apr 2017) | 6 lines
  
  create_and_open_dev() returns a (-errno), so the "if (iser_fd...)" check should
  detect *any* negative return value as a case when fd should be set to -1.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7109 | vlnb | 2017-04-13 15:38:38 -0700 (Thu, 13 Apr 2017) | 8 lines
  
  Change memcpy() to strncpy() because the source name string is not guaranteed
  to exist as valid addressable memory beyond the NULL byte.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
  
  with small addition to force set last byte NULL
........
  r7110 | vlnb | 2017-04-13 16:02:18 -0700 (Thu, 13 Apr 2017) | 7 lines
  
  Thre is potential buffer overflow in iscsi_session_alloc() due to
  short computation of needed string size.  Notice the "%s@%s" in the first call
  to sprintf().
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7111 | vlnb | 2017-04-13 16:12:46 -0700 (Thu, 13 Apr 2017) | 8 lines
  
  iscsi: avoid a crash in iscsi_extracheck_is_rd_thread()
  
  Add an extra check in iscsi_extracheck_is_rd_thread() to avoid a crash when
  conn->rd_task is NULL.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7115 | vlnb | 2017-04-13 16:37:13 -0700 (Thu, 13 Apr 2017) | 12 lines
  
  scst: fix memory leak in scst_proc_group_add()
  
  Valgrind noticed that the "name" allocated in scst_proc_group_add() was
  leaking.  It turns out that scst_alloc_add_acg makes its own copy of the name
  passed to it from this code, making the string duplication done here redundant
  (and leaky).  The change eliminates the string duplication (along with all its
  associated error handling logic) and simply passes the (unowned) incoming
  string down for duplication below.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7116 | vlnb | 2017-04-13 16:39:14 -0700 (Thu, 13 Apr 2017) | 7 lines
  
  scst_vdisk: fix memory leak in vdisk_write_proc()
  
  Another leak valgrind popped out, this one in vdisk_write_proc().
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7117 | vlnb | 2017-04-13 16:41:14 -0700 (Thu, 13 Apr 2017) | 9 lines
  
  scst: take scst_mutex before calling scst_del_free_acg() in exit_scst()
  
  scst_del_free_acg() does lockdep_assert_held(&scst_mutex), so we'd better take
  the lock before calling it.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7118 | vlnb | 2017-04-13 16:42:51 -0700 (Thu, 13 Apr 2017) | 8 lines
  
  scst: take scst_mutex before calling scst_del_free_acg() in scst_proc_cleanup_module()
  
  Take lock before a call that ends up at the lockdep_assert_held() in
  scst_del_free_acg() without locking.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7125 | vlnb | 2017-04-13 18:17:45 -0700 (Thu, 13 Apr 2017) | 6 lines
  
  extraclean does "rm tags cscope.out"
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7134 | vlnb | 2017-04-17 20:57:12 -0700 (Mon, 17 Apr 2017) | 5 lines
  
  iscsi-scst: replace strncpy() by strlcpy()
  
  Follow up for r7109: strlcpy() is more appropriate in this place.
........
  r7135 | vlnb | 2017-04-17 21:02:44 -0700 (Mon, 17 Apr 2017) | 5 lines
  
  fcst: Linux kernel v4.10 build fix
  
  Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
........
  r7136 | vlnb | 2017-04-17 21:06:18 -0700 (Mon, 17 Apr 2017) | 5 lines
  
  scst: avoid possible side effect with WARN_ON_ONCE()
  
  Reported-By: David Butterfield <dab21774@gmail.com>
........
  r7137 | vlnb | 2017-04-18 20:44:20 -0700 (Tue, 18 Apr 2017) | 5 lines
  
  fileio_tgt: change "#if DEBUG_TM_FN_IGNORE" to "#ifdef ..."
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7139 | vlnb | 2017-04-20 18:02:25 -0700 (Thu, 20 Apr 2017) | 7 lines
  
  iscsi-scstd: replace signal() with sigaction()
  
  Replace signal() with sigaction() for validity in a multithreaded process
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7141 | vlnb | 2017-04-20 18:11:37 -0700 (Thu, 20 Apr 2017) | 7 lines
  
  scst: set file size for NULLIO in PROCFS build
  
  The file size wasn't getting set for NULLIO with /proc support
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7143 | vlnb | 2017-04-20 18:32:07 -0700 (Thu, 20 Apr 2017) | 9 lines
  
  iscsi-scst: fix ENOMEM path
  
  In an error path in iscsi_threads_pool_get(), when a new pool cannot be
  allocated, if there is a pool on iscsi_thread_pools_list, it passes that back as
  an alternative, so return zero in that case.
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7152 | bvassche | 2017-04-26 16:53:11 -0700 (Wed, 26 Apr 2017) | 5 lines
  
  scst: Introduce scst_scsi_execute()
  
  This patch does not change any functionality but makes it easier
  to port SCST to Linux kernel v4.11.
........
  r7153 | bvassche | 2017-04-26 17:17:22 -0700 (Wed, 26 Apr 2017) | 1 line
  
  scst: Port to Linux kernel v4.11
........
  r7154 | vlnb | 2017-04-28 17:58:55 -0700 (Fri, 28 Apr 2017) | 5 lines
  
  scst: create proc/scst_threads with mode S_IRUGO, not 0
  
  Signed-off-by: David Butterfield <dab21774@gmail.com>
........
  r7158 | bvassche | 2017-05-01 14:01:33 -0700 (Mon, 01 May 2017) | 1 line
  
  scst: Kernel v4.12 build fixes
........
  r7162 | bvassche | 2017-05-02 07:13:15 -0700 (Tue, 02 May 2017) | 1 line
  
  scst_lib: Fix kernel 2.6.30 build
........
  r7163 | bvassche | 2017-05-02 07:23:00 -0700 (Tue, 02 May 2017) | 1 line
  
  scst: Fix build for kernels before v2.6.39
........
  r7168 | bvassche | 2017-05-03 19:56:27 -0700 (Wed, 03 May 2017) | 1 line
  
  scst: Fix build for kernels before v2.6.39
........
  r7169 | vlnb | 2017-05-05 18:31:59 -0700 (Fri, 05 May 2017) | 3 lines
  
  scst: nolockdep patch for kernel 4.9
........
  r7170 | vlnb | 2017-05-10 20:51:32 -0700 (Wed, 10 May 2017) | 3 lines
  
  qla2x00t: update to kernel 4.10
........
  r7171 | vlnb | 2017-05-10 20:52:51 -0700 (Wed, 10 May 2017) | 3 lines
  
  scst: nolockdep patch for kernel 4.10
........
  r7173 | vlnb | 2017-05-10 21:00:29 -0700 (Wed, 10 May 2017) | 7 lines
  
  fcst: Linux kernel v4.11 build fix
  
  Linux kernel v4.11 build fix.
  
  Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
........
  r7175 | bvassche | 2017-05-13 17:42:24 -0700 (Sat, 13 May 2017) | 4 lines
  
  scst/include/backport.h: Remove duplicate definition of kthread_create_on_node()
  
  This patch reverts most of r7168.
........
  r7176 | bvassche | 2017-05-13 17:55:39 -0700 (Sat, 13 May 2017) | 1 line
  
  scst/include/backport.h: Add a comment
........
  r7177 | bvassche | 2017-05-13 19:55:24 -0700 (Sat, 13 May 2017) | 1 line
  
  scst/include/backport.h: Fix kthread_create_on_node() definition
........
  r7178 | bvassche | 2017-05-13 20:06:54 -0700 (Sat, 13 May 2017) | 4 lines
  
  scst/include/backport.h: Add a kref_read() backport
  
  This patch does not change any functionality.
........
  r7179 | bvassche | 2017-05-13 20:13:56 -0700 (Sat, 13 May 2017) | 4 lines
  
  scst/include/backport.h: Add a backport of rcu_dereference_protected()
  
  This patch does not change any functionality.
........
  r7185 | bvassche | 2017-05-14 11:56:09 -0700 (Sun, 14 May 2017) | 14 lines
  
  scst_local: Fix a race condition
  
  Avoid that the following crash can occur:
  
  general protection fault: 0000 [#1] PREEMPT SMP
  RIP: 0010:scsi_is_host_device+0x7/0x20 [scsi_mod]
  Call Trace:
   scst_process_aens+0x95/0x1d0 [scst_local]
   scst_aen_work_fn+0x6f/0x120 [scst_local]
   process_one_work+0x20b/0x6c0
   worker_thread+0x4e/0x4a0
   kthread+0x113/0x150
   ret_from_fork+0x31/0x40
........
  r7190 | vlnb | 2017-05-19 20:00:28 -0700 (Fri, 19 May 2017) | 8 lines
  
  scst: fix possible NULL dereference in TM code
  
  TM command accessing a non-existing LUN might lead NULL dereference in
  scst_call_dev_task_mgmt_fn_done().
  
  Reported-By: <Ilan Steinberg <ilan.steinberg@kaminario.com>>
........
  r7193 | vlnb | 2017-05-22 19:23:38 -0700 (Mon, 22 May 2017) | 5 lines
  
  qla2x00t: fix broken 4.9 kernels build
  
  Reported-By: Marc Smith <marc.smith@parodyne.com>
........
  r7203 | vlnb | 2017-06-02 19:38:51 -0700 (Fri, 02 Jun 2017) | 3 lines
  
  Update to 4.11 kernels
........
  r7208 | vlnb | 2017-06-12 20:58:26 -0700 (Mon, 12 Jun 2017) | 5 lines
  
  scst: Linux kernel v4.12 warning fix.
  
  Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
........


git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.2.x@7209 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2017-07-14 00:17:31 +00:00

618 lines
16 KiB
C

/*
* Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
* Copyright (C) 2007 - 2016 Vladislav Bolkhovitin
* Copyright (C) 2007 - 2016 SanDisk Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
#include <linux/export.h>
#endif
#include "iscsi_trace_flag.h"
#include "iscsi.h"
/* target_mutex supposed to be locked */
struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid)
{
struct iscsi_session *session;
lockdep_assert_held(&target->target_mutex);
list_for_each_entry(session, &target->session_list,
session_list_entry) {
if (session->sid == sid)
return session;
}
return NULL;
}
/* target_mgmt_mutex supposed to be locked */
static int iscsi_session_alloc(struct iscsi_target *target,
struct iscsi_kern_session_info *info, struct iscsi_session **result)
{
int err;
unsigned int i;
struct iscsi_session *session;
char *name = NULL;
lockdep_assert_held(&target_mgmt_mutex);
session = kmem_cache_zalloc(iscsi_sess_cache, GFP_KERNEL);
if (!session)
return -ENOMEM;
session->target = target;
session->sid = info->sid;
atomic_set(&session->active_cmds, 0);
session->exp_cmd_sn = info->exp_cmd_sn;
session->initiator_name = kstrdup(info->initiator_name, GFP_KERNEL);
if (!session->initiator_name) {
err = -ENOMEM;
goto err;
}
#ifdef CONFIG_SCST_PROC
name = kmalloc(strlen(info->user_name) + strlen(info->initiator_name) +
2, GFP_KERNEL); /* +1 (for '\0') +1 (for '@') */
if (name == NULL) {
err = -ENOMEM;
goto err;
}
if (info->user_name[0] != '\0')
sprintf(name, "%s@%s", info->user_name, info->initiator_name);
else
sprintf(name, "%s", info->initiator_name);
#else
name = info->full_initiator_name;
#endif
INIT_LIST_HEAD(&session->conn_list);
INIT_LIST_HEAD(&session->pending_list);
spin_lock_init(&session->sn_lock);
spin_lock_init(&session->cmnd_data_wait_hash_lock);
for (i = 0; i < ARRAY_SIZE(session->cmnd_data_wait_hash); i++)
INIT_LIST_HEAD(&session->cmnd_data_wait_hash[i]);
session->next_ttt = 1;
session->scst_sess = scst_register_session(target->scst_tgt, 0,
name, session, NULL, NULL);
if (session->scst_sess == NULL) {
PRINT_ERROR("%s", "scst_register_session() failed");
err = -ENOMEM;
goto err;
}
if (!session->sess_params.rdma_extensions) {
err = iscsi_threads_pool_get(&session->scst_sess->acg->acg_cpu_mask,
&session->sess_thr_pool);
if (err != 0)
goto err_unreg;
}
#ifdef CONFIG_SCST_PROC
kfree(name);
#endif
TRACE(TRACE_MGMT, "Session %p created: target %p, tid %u, sid %#Lx, "
"initiator %s", session, target, target->tid, info->sid,
session->scst_sess->initiator_name);
*result = session;
return 0;
err_unreg:
scst_unregister_session(session->scst_sess, 1, NULL);
err:
if (session) {
kfree(session->initiator_name);
kmem_cache_free(iscsi_sess_cache, session);
#ifdef CONFIG_SCST_PROC
kfree(name);
#endif
}
return err;
}
/* target_mutex supposed to be locked */
void sess_reinst_finished(struct iscsi_session *sess)
{
struct iscsi_conn *c;
TRACE_ENTRY();
TRACE_MGMT_DBG("Enabling reinstate successor sess %p", sess);
lockdep_assert_held(&sess->target->target_mutex);
sBUG_ON(!sess->sess_reinstating);
list_for_each_entry(c, &sess->conn_list, conn_list_entry) {
conn_reinst_finished(c);
}
sess->sess_reinstating = 0;
TRACE_EXIT();
return;
}
/* target_mgmt_mutex supposed to be locked */
int __add_session(struct iscsi_target *target,
struct iscsi_kern_session_info *info)
{
struct iscsi_session *new_sess = NULL, *sess, *old_sess;
int err = 0, i;
union iscsi_sid sid;
bool reinstatement = false;
struct iscsi_kern_params_info *params_info;
TRACE_MGMT_DBG("Adding session SID %llx", info->sid);
lockdep_assert_held(&target_mgmt_mutex);
err = iscsi_session_alloc(target, info, &new_sess);
if (err != 0)
goto out;
mutex_lock(&target->target_mutex);
sess = session_lookup(target, info->sid);
if (sess != NULL) {
PRINT_ERROR("Attempt to add session with existing SID %llx",
info->sid);
err = -EEXIST;
goto out_err_unlock;
}
params_info = kmalloc(sizeof(*params_info), GFP_KERNEL);
if (params_info == NULL) {
PRINT_ERROR("Unable to allocate params info (size %zd)",
sizeof(*params_info));
err = -ENOMEM;
goto out_err_unlock;
}
sid = *(union iscsi_sid *)&info->sid;
sid.id.tsih = 0;
old_sess = NULL;
/*
* We need to find the latest session to correctly handle
* multi-reinstatements
*/
list_for_each_entry_reverse(sess, &target->session_list,
session_list_entry) {
union iscsi_sid s = *(union iscsi_sid *)&sess->sid;
s.id.tsih = 0;
if ((sid.id64 == s.id64) &&
(strcmp(info->initiator_name, sess->initiator_name) == 0)) {
if (!sess->sess_shutting_down) {
/* session reinstatement */
old_sess = sess;
}
break;
}
}
sess = NULL;
list_add_tail(&new_sess->session_list_entry, &target->session_list);
memset(params_info, 0, sizeof(*params_info));
params_info->tid = target->tid;
params_info->sid = info->sid;
params_info->params_type = key_session;
for (i = 0; i < session_key_last; i++)
params_info->session_params[i] = info->session_params[i];
err = iscsi_params_set(target, params_info, 1);
if (err != 0)
goto out_del;
memset(params_info, 0, sizeof(*params_info));
params_info->tid = target->tid;
params_info->sid = info->sid;
params_info->params_type = key_target;
for (i = 0; i < target_key_last; i++)
params_info->target_params[i] = info->target_params[i];
err = iscsi_params_set(target, params_info, 1);
if (err != 0)
goto out_del;
kfree(params_info);
params_info = NULL;
if (old_sess != NULL) {
reinstatement = true;
TRACE_MGMT_DBG("Reinstating sess %p with SID %llx (old %p, "
"SID %llx)", new_sess, new_sess->sid, old_sess,
old_sess->sid);
new_sess->sess_reinstating = 1;
old_sess->sess_reinst_successor = new_sess;
target_del_session(old_sess->target, old_sess, 0);
}
mutex_unlock(&target->target_mutex);
if (reinstatement) {
/*
* Mutex target_mgmt_mutex won't allow to add connections to
* the new session after target_mutex was dropped, so it's safe
* to replace the initial UA without it. We can't do it under
* target_mutex, because otherwise we can establish a
* circular locking dependency between target_mutex and
* scst_mutex in SCST core (iscsi_report_aen() called by
* SCST core under scst_mutex).
*/
scst_set_initial_UA(new_sess->scst_sess,
SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
}
out:
return err;
out_del:
list_del(&new_sess->session_list_entry);
kfree(params_info);
out_err_unlock:
mutex_unlock(&target->target_mutex);
scst_unregister_session(new_sess->scst_sess, 1, NULL);
new_sess->scst_sess = NULL;
mutex_lock(&target->target_mutex);
session_free(new_sess, false);
mutex_unlock(&target->target_mutex);
goto out;
}
static void __session_free(struct iscsi_session *session)
{
kfree(session->initiator_name);
kmem_cache_free(iscsi_sess_cache, session);
}
static void iscsi_unreg_sess_done(struct scst_session *scst_sess)
{
struct iscsi_session *session;
TRACE_ENTRY();
session = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
session->scst_sess = NULL;
__session_free(session);
TRACE_EXIT();
return;
}
/* target_mutex supposed to be locked */
int session_free(struct iscsi_session *session, bool del)
{
unsigned int i;
TRACE(TRACE_MGMT, "Freeing session %p (SID %llx)",
session, session->sid);
lockdep_assert_held(&session->target->target_mutex);
sBUG_ON(!list_empty(&session->conn_list));
if (unlikely(atomic_read(&session->active_cmds) != 0)) {
PRINT_CRIT_ERROR("active_cmds not 0 (%d)!!",
atomic_read(&session->active_cmds));
sBUG();
}
for (i = 0; i < ARRAY_SIZE(session->cmnd_data_wait_hash); i++)
sBUG_ON(!list_empty(&session->cmnd_data_wait_hash[i]));
if (session->sess_reinst_successor != NULL)
sess_reinst_finished(session->sess_reinst_successor);
if (session->sess_reinstating) {
struct iscsi_session *s;
TRACE_MGMT_DBG("Freeing being reinstated sess %p", session);
list_for_each_entry(s, &session->target->session_list,
session_list_entry) {
if (s->sess_reinst_successor == session) {
s->sess_reinst_successor = NULL;
break;
}
}
}
if (del)
list_del(&session->session_list_entry);
if (session->sess_thr_pool != NULL) {
iscsi_threads_pool_put(session->sess_thr_pool);
session->sess_thr_pool = NULL;
}
if (session->scst_sess != NULL) {
/*
* We must NOT call scst_unregister_session() in the waiting
* mode, since we are under target_mutex. Otherwise we can
* establish a circular locking dependency between target_mutex
* and scst_mutex in SCST core (iscsi_report_aen() called by
* SCST core under scst_mutex).
*/
scst_unregister_session(session->scst_sess, 0,
iscsi_unreg_sess_done);
} else
__session_free(session);
return 0;
}
/* target_mutex supposed to be locked */
int __del_session(struct iscsi_target *target, u64 sid)
{
struct iscsi_session *session;
lockdep_assert_held(&target->target_mutex);
session = session_lookup(target, sid);
if (!session)
return -ENOENT;
if (!list_empty(&session->conn_list)) {
PRINT_ERROR("%llx still have connections",
(unsigned long long int)session->sid);
return -EBUSY;
}
return session_free(session, true);
}
/* Must be called under target_mutex */
void iscsi_sess_force_close(struct iscsi_session *sess)
{
struct iscsi_conn *conn;
TRACE_ENTRY();
lockdep_assert_held(&sess->target->target_mutex);
PRINT_INFO("Force closing session %llx with initiator %s (%p)",
(unsigned long long int)sess->sid, sess->initiator_name, sess);
list_for_each_entry(conn, &sess->conn_list, conn_list_entry) {
TRACE(TRACE_MGMT, "Force closing connection %p", conn);
__mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
}
TRACE_EXIT();
return;
}
#ifdef CONFIG_SCST_PROC
/* target_mutex supposed to be locked */
static void iscsi_session_info_show(struct seq_file *seq,
struct iscsi_target *target)
{
struct iscsi_session *session;
lockdep_assert_held(&target->target_mutex);
list_for_each_entry(session, &target->session_list,
session_list_entry) {
seq_printf(seq, "\tsid:%llx initiator:%s (reinstating %s)\n",
(unsigned long long int)session->sid,
session->initiator_name,
session->sess_reinstating ? "yes" : "no");
conn_info_show(seq, session);
}
return;
}
static int iscsi_session_seq_open(struct inode *inode, struct file *file)
{
int res;
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5
res = seq_open(file, (struct seq_operations *)&iscsi_seq_op);
#else
res = seq_open(file, &iscsi_seq_op);
#endif
if (!res)
((struct seq_file *)file->private_data)->private =
iscsi_session_info_show;
return res;
}
const struct file_operations session_seq_fops = {
.owner = THIS_MODULE,
.open = iscsi_session_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#else /* CONFIG_SCST_PROC */
#define ISCSI_SESS_BOOL_PARAM_ATTR(name, exported_name) \
static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
struct kobj_attribute *attr, char *buf) \
{ \
int pos; \
struct scst_session *scst_sess; \
struct iscsi_session *sess; \
\
scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
\
pos = sprintf(buf, "%s\n", \
iscsi_get_bool_value(sess->sess_params.name)); \
\
return pos; \
} \
\
static struct kobj_attribute iscsi_sess_attr_##name = \
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL)
#define ISCSI_SESS_INT_PARAM_ATTR(name, exported_name) \
static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
struct kobj_attribute *attr, char *buf) \
{ \
int pos; \
struct scst_session *scst_sess; \
struct iscsi_session *sess; \
\
scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
\
pos = sprintf(buf, "%d\n", sess->sess_params.name); \
\
return pos; \
} \
\
static struct kobj_attribute iscsi_sess_attr_##name = \
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL)
#define ISCSI_SESS_DIGEST_PARAM_ATTR(name, exported_name) \
static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
struct kobj_attribute *attr, char *buf) \
{ \
int pos; \
struct scst_session *scst_sess; \
struct iscsi_session *sess; \
char digest_name[64]; \
\
scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
\
pos = sprintf(buf, "%s\n", iscsi_get_digest_name( \
sess->sess_params.name, digest_name)); \
\
return pos; \
} \
\
static struct kobj_attribute iscsi_sess_attr_##name = \
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL)
ISCSI_SESS_BOOL_PARAM_ATTR(initial_r2t, InitialR2T);
ISCSI_SESS_BOOL_PARAM_ATTR(immediate_data, ImmediateData);
ISCSI_SESS_INT_PARAM_ATTR(max_recv_data_length, MaxRecvDataSegmentLength);
ISCSI_SESS_INT_PARAM_ATTR(max_xmit_data_length, MaxXmitDataSegmentLength);
ISCSI_SESS_INT_PARAM_ATTR(max_burst_length, MaxBurstLength);
ISCSI_SESS_INT_PARAM_ATTR(first_burst_length, FirstBurstLength);
ISCSI_SESS_INT_PARAM_ATTR(max_outstanding_r2t, MaxOutstandingR2T);
ISCSI_SESS_DIGEST_PARAM_ATTR(header_digest, HeaderDigest);
ISCSI_SESS_DIGEST_PARAM_ATTR(data_digest, DataDigest);
static ssize_t iscsi_sess_sid_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
int pos;
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);
pos = sprintf(buf, "%llx\n", sess->sid);
TRACE_EXIT_RES(pos);
return pos;
}
static struct kobj_attribute iscsi_attr_sess_sid =
__ATTR(sid, S_IRUGO, iscsi_sess_sid_show, NULL);
static ssize_t iscsi_sess_reinstating_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
int pos;
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);
pos = sprintf(buf, "%d\n", sess->sess_reinstating ? 1 : 0);
TRACE_EXIT_RES(pos);
return pos;
}
static struct kobj_attribute iscsi_sess_attr_reinstating =
__ATTR(reinstating, S_IRUGO, iscsi_sess_reinstating_show, NULL);
static ssize_t iscsi_sess_thread_pid_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct scst_session *scst_sess = container_of(kobj, struct scst_session,
sess_kobj);
struct iscsi_session *sess = scst_sess_get_tgt_priv(scst_sess);
struct iscsi_thread_pool *thr_pool = sess->sess_thr_pool;
struct iscsi_thread *t;
int res = -ENOENT;
if (!thr_pool)
goto out;
res = 0;
mutex_lock(&thr_pool->tp_mutex);
list_for_each_entry(t, &thr_pool->threads_list, threads_list_entry)
res += scnprintf(buf + res, PAGE_SIZE - res, "%d%s",
task_pid_vnr(t->thr),
list_is_last(&t->threads_list_entry,
&thr_pool->threads_list) ?
"\n" : " ");
mutex_unlock(&thr_pool->tp_mutex);
out:
return res;
}
static struct kobj_attribute iscsi_sess_thread_pid =
__ATTR(thread_pid, S_IRUGO, iscsi_sess_thread_pid_show, NULL);
const struct attribute *iscsi_sess_attrs[] = {
&iscsi_sess_attr_initial_r2t.attr,
&iscsi_sess_attr_immediate_data.attr,
&iscsi_sess_attr_max_recv_data_length.attr,
&iscsi_sess_attr_max_xmit_data_length.attr,
&iscsi_sess_attr_max_burst_length.attr,
&iscsi_sess_attr_first_burst_length.attr,
&iscsi_sess_attr_max_outstanding_r2t.attr,
&iscsi_sess_attr_header_digest.attr,
&iscsi_sess_attr_data_digest.attr,
&iscsi_attr_sess_sid.attr,
&iscsi_sess_attr_reinstating.attr,
&iscsi_sess_thread_pid.attr,
NULL,
};
#endif /* CONFIG_SCST_PROC */