[PATCH 12/15] target: add callout to test a session

2018-07-15 Thread Mike Christie
This adds a callout and configfs file so userspace apps can
test a session. It is useful for apps that do not want
to enable target nops that may disrupt normal traffic
and only want to test it during specific events like
failover/failbacks when there might be multiple sessions
to the same target port.

Signed-off-by: Mike Christie 
---
 drivers/target/iscsi/iscsi_target_login.c|  2 +-
 drivers/target/target_core_fabric_configfs.c | 71 ++--
 drivers/target/target_core_transport.c   | 20 +---
 include/target/target_core_base.h|  1 +
 include/target/target_core_fabric.h  |  7 ++-
 5 files changed, 88 insertions(+), 13 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target_login.c 
b/drivers/target/iscsi/iscsi_target_login.c
index 48a9522..8f219b9 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -353,7 +353,7 @@ static int iscsi_login_zero_tsih_s1(
return -ENOMEM;
}
 
-   sess->se_sess = transport_alloc_session(TARGET_PROT_NORMAL);
+   sess->se_sess = transport_alloc_session(&iscsi_ops, TARGET_PROT_NORMAL);
if (IS_ERR(sess->se_sess)) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
diff --git a/drivers/target/target_core_fabric_configfs.c 
b/drivers/target/target_core_fabric_configfs.c
index 2deda28..a5bb9a1 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -937,7 +937,48 @@ static ssize_t target_fabric_session_initiator_port_show(
return len;
 }
 
+static ssize_t target_fabric_session_test_store(
+   struct config_item *item, const char *page, size_t count)
+{
+   struct se_session *se_sess = container_of(to_config_group(item),
+ struct se_session, group);
+   struct se_portal_group *se_tpg;
+   unsigned long flags;
+
+   int ret;
+   u8 val;
+
+   ret = kstrtou8(page, 0, &val);
+   if (ret < 0)
+   return ret;
+
+   spin_lock_irqsave(&se_sess->configfs_lock, flags);
+   se_tpg = se_sess->se_tpg;
+   if (!se_tpg) {
+   ret = -ENOTCONN;
+   goto unlock;
+   }
+
+   if (!config_item_get_unless_zero(&se_tpg->tpg_group.cg_item)) {
+   ret = -ENOTCONN;
+   goto unlock;
+   }
+   spin_unlock_irqrestore(&se_sess->configfs_lock, flags);
+
+   ret = se_tpg->se_tpg_tfo->test_session(se_sess, val);
+   if (!ret)
+   ret = count;
+
+   config_item_put(&se_tpg->tpg_group.cg_item);
+   return ret;
+
+unlock:
+   spin_unlock_irqrestore(&se_sess->configfs_lock, flags);
+   return ret;
+}
+
 CONFIGFS_ATTR_RO(target_fabric_session_, initiator_port);
+CONFIGFS_ATTR_WO(target_fabric_session_, test);
 
 static struct configfs_attribute *target_fabric_session_attrs[] = {
&target_fabric_session_attr_initiator_port,
@@ -955,8 +996,11 @@ static struct configfs_item_operations 
target_session_item_ops = {
.release= target_fabric_session_release,
 };
 
-int target_fabric_init_session(struct se_session *se_sess)
+int target_fabric_init_session(const struct target_core_fabric_ops *tfo,
+  struct se_session *se_sess)
 {
+   struct configfs_attribute **attrs;
+   int len = 0, i, ret;
char *name;
 
name = kasprintf(GFP_KERNEL, "%d", se_sess->sid);
@@ -965,10 +1009,31 @@ int target_fabric_init_session(struct se_session 
*se_sess)
 
se_sess->cit.ct_owner = THIS_MODULE;
se_sess->cit.ct_item_ops = &target_session_item_ops;
-   se_sess->cit.ct_attrs = target_fabric_session_attrs;
+
+   for (i = 0; target_fabric_session_attrs[i] != NULL; i++)
+   len += sizeof(struct configfs_attribute *);
+   if (tfo->test_session)
+   len += sizeof(struct configfs_attribute *);
+
+   attrs = kzalloc(len, GFP_KERNEL);
+   if (!attrs) {
+   ret = -ENOMEM;
+   goto free_name;
+   }
+
+   for (i = 0; target_fabric_session_attrs[i] != NULL; i++)
+   attrs[i] = target_fabric_session_attrs[i];
+
+   if (tfo->test_session)
+   attrs[i] = &target_fabric_session_attr_test;
+
+   se_sess->cit.ct_attrs = se_sess->attrs = attrs;
+
config_group_init_type_name(&se_sess->group, name, &se_sess->cit);
+   ret = 0;
+free_name:
kfree(name);
-   return 0;
+   return ret;
 }
 EXPORT_SYMBOL(target_fabric_init_session);
 
diff --git a/drivers/target/target_core_transport.c 
b/drivers/target/target_core_transport.c
index 04ef13c..5f0f7a4 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -245,9 +245,11 @@ EXPORT_SYMBOL(transport_init_session);
 
 /**
  * transport_alloc_session - allocate a session o

Re: [PATCH 12/15] target: add callout to test a session

2018-07-18 Thread Bart Van Assche
On Sun, 2018-07-15 at 18:16 -0500, Mike Christie wrote:
> +   int (*test_session)(struct se_session *, u8 timeout);

Does any of the patches in this series define a test_session callback
function?

What is the unit of the timeout parameter? 1/HZ, ms or s?

Thanks,

Bart.

Re: [PATCH 12/15] target: add callout to test a session

2018-07-18 Thread Mike Christie
On 07/18/2018 05:46 PM, Bart Van Assche wrote:
> On Sun, 2018-07-15 at 18:16 -0500, Mike Christie wrote:
>> +   int (*test_session)(struct se_session *, u8 timeout);
> 
> Does any of the patches in this series define a test_session callback
> function?

Patch 14 does.

> 
> What is the unit of the timeout parameter? 1/HZ, ms or s?
> 

It is seconds.

I will add comments to document the callout requirements and arguments.

> Thanks,
> 
> Bart.
>