All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RESEND v4] iscsi: Report connection state on sysfs
@ 2020-03-17 23:34 Gabriel Krisman Bertazi
  2020-03-19 17:31 ` Lee Duncan
  2020-03-27  2:00 ` Martin K. Petersen
  0 siblings, 2 replies; 3+ messages in thread
From: Gabriel Krisman Bertazi @ 2020-03-17 23:34 UTC (permalink / raw)
  To: lduncan
  Cc: bvanassche, open-iscsi, cleech, martin.petersen, linux-scsi,
	Gabriel Krisman Bertazi, kernel, Khazhismel Kumykov, Junho Ryu

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 <khazhy@google.com>
Suggested-by: Junho Ryu <jayr@google.com>
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
---
Changes since v3:
  - Change state type to enum (Bart)

Changes since v2:
  - Use designated initializers (Bart)

Changes since v1:
  - Remove dependency of state values (Bart)

 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..0ec1b31c75a9 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 char *const connection_state_names[] = {
+	[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);
+	const char *state = "unknown";
+
+	if (conn->state >= 0 &&
+	    conn->state < ARRAY_SIZE(connection_state_names))
+		state = connection_state_names[conn->state];
+
+	return sprintf(buf, "%s\n", state);
+}
+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..bdcb6d69d154 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_connection_state {
+	ISCSI_CONN_UP = 0,
+	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 */
+	enum iscsi_connection_state state;
 };
 
 #define iscsi_dev_to_conn(_dev) \
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH RESEND v4] iscsi: Report connection state on sysfs
  2020-03-17 23:34 [PATCH RESEND v4] iscsi: Report connection state on sysfs Gabriel Krisman Bertazi
@ 2020-03-19 17:31 ` Lee Duncan
  2020-03-27  2:00 ` Martin K. Petersen
  1 sibling, 0 replies; 3+ messages in thread
From: Lee Duncan @ 2020-03-19 17:31 UTC (permalink / raw)
  To: Gabriel Krisman Bertazi
  Cc: bvanassche, open-iscsi, cleech, martin.petersen, linux-scsi,
	kernel, Khazhismel Kumykov, Junho Ryu

On 3/17/20 4:34 PM, Gabriel Krisman Bertazi wrote:
> 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 <khazhy@google.com>
> Suggested-by: Junho Ryu <jayr@google.com>
> Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
> ---
> Changes since v3:
>   - Change state type to enum (Bart)
> 
> Changes since v2:
>   - Use designated initializers (Bart)
> 
> Changes since v1:
>   - Remove dependency of state values (Bart)
> 
>  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..0ec1b31c75a9 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 char *const connection_state_names[] = {
> +	[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);
> +	const char *state = "unknown";
> +
> +	if (conn->state >= 0 &&
> +	    conn->state < ARRAY_SIZE(connection_state_names))
> +		state = connection_state_names[conn->state];
> +
> +	return sprintf(buf, "%s\n", state);
> +}
> +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..bdcb6d69d154 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_connection_state {
> +	ISCSI_CONN_UP = 0,
> +	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 */
> +	enum iscsi_connection_state state;
>  };
>  
>  #define iscsi_dev_to_conn(_dev) \
> 

Reviewed-by: Lee Duncan <lduncan@suse.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH RESEND v4] iscsi: Report connection state on sysfs
  2020-03-17 23:34 [PATCH RESEND v4] iscsi: Report connection state on sysfs Gabriel Krisman Bertazi
  2020-03-19 17:31 ` Lee Duncan
@ 2020-03-27  2:00 ` Martin K. Petersen
  1 sibling, 0 replies; 3+ messages in thread
From: Martin K. Petersen @ 2020-03-27  2:00 UTC (permalink / raw)
  To: Gabriel Krisman Bertazi
  Cc: lduncan, bvanassche, open-iscsi, cleech, martin.petersen,
	linux-scsi, kernel, Khazhismel Kumykov, Junho Ryu


Gabriel,

> 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.

Applied to 5.7/scsi-queue, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-03-27  2:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-17 23:34 [PATCH RESEND v4] iscsi: Report connection state on sysfs Gabriel Krisman Bertazi
2020-03-19 17:31 ` Lee Duncan
2020-03-27  2:00 ` Martin K. Petersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.