From patchwork Sun Jul 15 23:16:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Christie X-Patchwork-Id: 10525343 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B9203602B3 for ; Sun, 15 Jul 2018 23:16:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A9ED02654B for ; Sun, 15 Jul 2018 23:16:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E5F628334; Sun, 15 Jul 2018 23:16:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 014262654B for ; Sun, 15 Jul 2018 23:16:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727436AbeGOXlZ (ORCPT ); Sun, 15 Jul 2018 19:41:25 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48848 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727349AbeGOXlY (ORCPT ); Sun, 15 Jul 2018 19:41:24 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 314767DAC6; Sun, 15 Jul 2018 23:16:50 +0000 (UTC) Received: from rh2.redhat.com (ovpn-120-206.rdu2.redhat.com [10.10.120.206]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7A54476EA; Sun, 15 Jul 2018 23:16:48 +0000 (UTC) From: Mike Christie To: linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, nab@linux-iscsi.org Cc: Mike Christie Subject: [PATCH 12/15] target: add callout to test a session Date: Sun, 15 Jul 2018 18:16:28 -0500 Message-Id: <1531696591-8558-13-git-send-email-mchristi@redhat.com> In-Reply-To: <1531696591-8558-1-git-send-email-mchristi@redhat.com> References: <1531696591-8558-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sun, 15 Jul 2018 23:16:50 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sun, 15 Jul 2018 23:16:50 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'mchristi@redhat.com' RCPT:'' Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 object and initialize it + * @tfo: pointer to fabric ops template. * @sup_prot_ops: bitmask that defines which T10-PI modes are supported. */ -struct se_session *transport_alloc_session(enum target_prot_op sup_prot_ops) +struct se_session *transport_alloc_session(const struct target_core_fabric_ops *tfo, + enum target_prot_op sup_prot_ops) { struct se_session *se_sess; unsigned long flags; @@ -275,7 +277,7 @@ struct se_session *transport_alloc_session(enum target_prot_op sup_prot_ops) goto free_sess; } - ret = target_fabric_init_session(se_sess); + ret = target_fabric_init_session(tfo, se_sess); if (ret) goto free_sid; @@ -329,13 +331,15 @@ EXPORT_SYMBOL(transport_alloc_session_tags); /** * transport_init_session_tags - allocate a session and target driver private data + * @tfo: pointer to fabric ops template. * @tag_num: Maximum number of in-flight commands between initiator and target. * @tag_size: Size in bytes of the private data a target driver associates with * each command. * @sup_prot_ops: bitmask that defines which T10-PI modes are supported. */ static struct se_session * -transport_init_session_tags(unsigned int tag_num, unsigned int tag_size, +transport_init_session_tags(const struct target_core_fabric_ops *tfo, + unsigned int tag_num, unsigned int tag_size, enum target_prot_op sup_prot_ops) { struct se_session *se_sess; @@ -352,7 +356,7 @@ transport_init_session_tags(unsigned int tag_num, unsigned int tag_size, return ERR_PTR(-EINVAL); } - se_sess = transport_alloc_session(sup_prot_ops); + se_sess = transport_alloc_session(tfo, sup_prot_ops); if (IS_ERR(se_sess)) return se_sess; @@ -465,9 +469,10 @@ target_setup_session(struct se_portal_group *tpg, * of I/O descriptor tags, go ahead and perform that setup now.. */ if (tag_num != 0) - sess = transport_init_session_tags(tag_num, tag_size, prot_op); + sess = transport_init_session_tags(tpg->se_tpg_tfo, tag_num, + tag_size, prot_op); else - sess = transport_alloc_session(prot_op); + sess = transport_alloc_session(tpg->se_tpg_tfo, prot_op); if (IS_ERR(sess)) return sess; @@ -591,6 +596,7 @@ void target_release_session(struct se_session *se_sess) idr_remove(&se_sess_idr, se_sess->sid); spin_unlock_irqrestore(&se_sess_idr_lock, flags); + kfree(se_sess->attrs); kmem_cache_free(se_sess_cache, se_sess); } @@ -653,9 +659,9 @@ void transport_deregister_session(struct se_session *se_sess) spin_lock_irqsave(&se_tpg->session_lock, flags); list_del(&se_sess->sess_list); - se_sess->fabric_sess_ptr = NULL; spin_lock(&se_sess->configfs_lock); + se_sess->fabric_sess_ptr = NULL; se_sess->se_tpg = NULL; spin_unlock(&se_sess->configfs_lock); spin_unlock_irqrestore(&se_tpg->session_lock, flags); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index d3bb76c..d78e316 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -611,6 +611,7 @@ struct se_session { void *sess_cmd_map; struct sbitmap_queue sess_tag_pool; int sid; + struct configfs_attribute **attrs; struct config_group group; struct config_item_type cit; }; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 36077d6..7eacfdd 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -56,6 +56,7 @@ struct target_core_fabric_ops { int (*check_stop_free)(struct se_cmd *); void (*release_cmd)(struct se_cmd *); void (*close_session)(struct se_session *); + int (*test_session)(struct se_session *, u8 timeout); /* * Used only for SCSI fabrics that contain multi-value TransportIDs * (like iSCSI). All other SCSI fabrics should set this to NULL. @@ -116,7 +117,8 @@ struct se_session *target_setup_session(struct se_portal_group *, void target_remove_session(struct se_session *); void transport_init_session(struct se_session *); -struct se_session *transport_alloc_session(enum target_prot_op); +struct se_session *transport_alloc_session( + const struct target_core_fabric_ops *tfo, enum target_prot_op); int transport_alloc_session_tags(struct se_session *, unsigned int, unsigned int); void __transport_register_session(struct se_portal_group *, @@ -128,7 +130,8 @@ void transport_free_session(struct se_session *); void target_put_nacl(struct se_node_acl *); void transport_deregister_session_configfs(struct se_session *); void transport_deregister_session(struct se_session *); -int target_fabric_init_session(struct se_session *); +int target_fabric_init_session(const struct target_core_fabric_ops *tfo, + struct se_session *); int target_fabric_register_session(struct se_portal_group *, struct se_session *); void target_fabric_unregister_session(struct se_session *);