From patchwork Wed Mar 4 22:57:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel Krisman Bertazi X-Patchwork-Id: 11420943 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CCE3E17E0 for ; Wed, 4 Mar 2020 22:57:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B6E1C20848 for ; Wed, 4 Mar 2020 22:57:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388476AbgCDW5M (ORCPT ); Wed, 4 Mar 2020 17:57:12 -0500 Received: from bhuna.collabora.co.uk ([46.235.227.227]:47458 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387931AbgCDW5M (ORCPT ); Wed, 4 Mar 2020 17:57:12 -0500 Received: from localhost (unknown [IPv6:2610:98:8005::7c7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: krisman) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 3090229139D; Wed, 4 Mar 2020 22:57:10 +0000 (GMT) From: Gabriel Krisman Bertazi To: lduncan@suse.com Cc: cleech@redhat.com, martin.petersen@oracle.com, open-iscsi@googlegroups.com, linux-scsi@vger.kernel.org, Gabriel Krisman Bertazi , kernel@collabora.com, Khazhismel Kumykov , Junho Ryu Subject: [PATCH] iscsi: Report connection state on sysfs Date: Wed, 4 Mar 2020 17:57:04 -0500 Message-Id: <20200304225704.1221703-1-krisman@collabora.com> X-Mailer: git-send-email 2.25.0 MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org If an iSCSI connection happens to fail while the daemon isn't running (due to a crash or for another reason), the kernel failure report is not received. When the daemon restarts, there is insufficient kernel state in sysfs for it to know that this happened. open-iscsi tries to reopen every connection, but on different initiators, we'd like to know which connections have failed. There is session->state, but that has a different lifetime than an iSCSI connection, so it doesn't directly relflect the connection state. Cc: Khazhismel Kumykov Suggested-by: Junho Ryu Signed-off-by: Gabriel Krisman Bertazi --- drivers/scsi/libiscsi.c | 7 ++++++- drivers/scsi/scsi_transport_iscsi.c | 29 ++++++++++++++++++++++++++++- include/scsi/scsi_transport_iscsi.h | 8 ++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 70b99c0e2e67..ca488c57ead4 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -3153,13 +3153,18 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) switch (flag) { case STOP_CONN_RECOVER: + cls_conn->state = ISCSI_CONN_FAILED; + break; case STOP_CONN_TERM: - iscsi_start_session_recovery(session, conn, flag); + cls_conn->state = ISCSI_CONN_DOWN; break; default: iscsi_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n", flag); + return; } + + iscsi_start_session_recovery(session, conn, flag); } EXPORT_SYMBOL_GPL(iscsi_conn_stop); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 17a45716a0fe..5b0e7df92964 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2276,6 +2276,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) INIT_LIST_HEAD(&conn->conn_list_err); conn->transport = transport; conn->cid = cid; + conn->state = ISCSI_CONN_DOWN; /* this is released in the dev's release function */ if (!get_device(&session->dev)) @@ -3709,8 +3710,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) break; case ISCSI_UEVENT_START_CONN: conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); - if (conn) + if (conn) { ev->r.retcode = transport->start_conn(conn); + if (!ev->r.retcode) + conn->state = ISCSI_CONN_UP; + } else err = -EINVAL; break; @@ -3907,6 +3911,26 @@ iscsi_conn_attr(tcp_xmit_wsf, ISCSI_PARAM_TCP_XMIT_WSF); iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF); iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR); +static const struct { + int state; + char *name; +} connection_state_name[] = { + {ISCSI_CONN_UP, "up"}, + {ISCSI_CONN_DOWN, "down"}, + {ISCSI_CONN_FAILED, "failed"} +}; + +static ssize_t +show_conn_state(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); + + return sprintf(buf, "%s\n", + connection_state_name[conn->state].name); +} +static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state, + NULL); #define iscsi_conn_ep_attr_show(param) \ static ssize_t show_conn_ep_param_##param(struct device *dev, \ @@ -3976,6 +4000,7 @@ static struct attribute *iscsi_conn_attrs[] = { &dev_attr_conn_tcp_xmit_wsf.attr, &dev_attr_conn_tcp_recv_wsf.attr, &dev_attr_conn_local_ipaddr.attr, + &dev_attr_conn_state.attr, NULL, }; @@ -4047,6 +4072,8 @@ static umode_t iscsi_conn_attr_is_visible(struct kobject *kobj, param = ISCSI_PARAM_TCP_RECV_WSF; else if (attr == &dev_attr_conn_local_ipaddr.attr) param = ISCSI_PARAM_LOCAL_IPADDR; + else if (attr == &dev_attr_conn_state.attr) + return S_IRUGO; else { WARN_ONCE(1, "Invalid conn attr"); return 0; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index fa8814245796..b19138a4a774 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -188,6 +188,13 @@ extern void iscsi_ping_comp_event(uint32_t host_no, uint32_t status, uint32_t pid, uint32_t data_size, uint8_t *data); +/* iscsi class connection state */ +enum { + ISCSI_CONN_UP, + ISCSI_CONN_DOWN, + ISCSI_CONN_FAILED, +}; + struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ struct list_head conn_list_err; /* item in connlist_err */ @@ -198,6 +205,7 @@ struct iscsi_cls_conn { struct iscsi_endpoint *ep; struct device dev; /* sysfs transport/container device */ + int state; }; #define iscsi_dev_to_conn(_dev) \