Re: [PATCH RESEND v4] iscsi: Report connection state on sysfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
> Suggested-by: Junho Ryu <jayr@xxxxxxxxxx>
> Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxxxxxxxx>
> ---
> 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@xxxxxxxx>



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux