Richard Sharpe | 31 Mar 04:01 2016
Picon

Patch: It is not necessary to try to increase the priority of the wq thread from userspace

Hi folks,

We recently found that iscsid was iterating through /proc/≤pid>/stat
looking for the workqueue iscsi-q-NN and then setting its nice value
to -20.

Then we investigated some more because it seemed like this could be
more easily done from the kernel.

What we discovered is that with modern Linux kernels, at least since
3.10.0 and possibly earlier, the thread called <wq-name> is not the
actual workqueue thread, it is the rescue thread for the workqueue,
and it already runs at -20!

Indeed, the work items are handled on a pool of threads.

This patch removes that call and code as it is redundant and actually
causes things to take longer and is a problem when you are trying to
start hundreds of iSCSI sessions.

There is another patch for the LLD to use a WQ_HIGHPRI queue to
achieve the original intent.

-- 
Regards,
Richard Sharpe
(何以解憂?唯有杜康。--曹操)

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
(Continue reading)

Bart Van Assche | 28 Mar 22:39 2016

[PATCH 0/5] Fix several static checker warnings reported against the iSCSI kernel code

Hello Mike,

These five patches are what I came up with after analyzing the output of 
"make M=drivers/scsi W=1 C=2" for the iSCSI kernel code. Please consider 
these patches for inclusion in kernel v4.7. The actual patches are:

0001-libiscsi-Unexport-iscsi_eh_target_reset.patch
0002-libiscsi-Remove-set-but-not-used-variables.patch
0003-scsi_transport_iscsi-Remove-set-but-not-used-variabl.patch
0004-scsi_transport_iscsi-Unexport-iscsi_is_flashnode_con.patch
0005-scsi_transport_iscsi-Declare-local-symbols-static.patch

Thanks,

Bart.

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

zhdscuch | 17 Mar 14:32 2016
Picon

"iscsi-initiator-utils" cannot recognize NIC ports

Hi!

I'm in trouble with "iscsi-initiator-utils" and my iscsi target.
I have a Dell T420 server and a Dell SCv2000 storage.The server is installed with two NICs and "iscsi-initiator-utils" software.
The SCv2000 is the target I want to connect to.Each NIC has two ports,however, the target seems to recognize only one port.

After the installation of "iscsi-initiator-utils" , a file named initiatorname.iscsi are created.In my view,iscsi will assign an initiator name for the recognized port.
There is only one initiatorname in my file rather than four.I attemptted to add initiatornames into it,but it was of no use.

The initiator and the target were well configured once, but one of the two NICs has some quality problems.I changed a new one  and configured them as before,
they crashed.I don't know what to do next.Can you help me?
Thx.

--
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.
d.graham.welsh | 11 Mar 20:03 2016
Picon

Can not see my target

Hello folks,

I can not seem to get my open-iscsi intiator to see my target.

When I attempt to discover my target, I get the following :

root <at> control:/home/Administrator# iscsiadm -m discovery -t sendtargets -p 192.168.122.9
iscsiadm: No portals found

I can ping 192.168.122.9, and nmap shows the target listening at port 3260.

Starting Nmap 6.00 ( http://nmap.org ) at 2016-03-11 10:58 AST
Nmap scan report for NAS.seamine.local (192.168.122.9)
Host is up (0.000085s latency).
Not shown: 995 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
111/tcp   open  rpcbind
3260/tcp  open  iscsi <-------
6000/tcp  open  X11
10000/tcp open  snet-sensor-mgmt
MAC Address: 00:24:E8:10:EF:82 (Dell)

Nmap done: 1 IP address (1 host up) scanned in 0.26 seconds

Strangely enough, if I type just iscsiadm -m discovery I get this :

root <at> control:/home/Administrator# iscsiadm -m discovery
NAS.seamine.local:3260 via sendtargets
192.168.122.9:3260 via sendtargets

So, it seems as if it sees the target, but won't acknowledge its existence.

I'm running the initiator on a Univention 4.1 server (which is Debian, basically). The target is a CentOS 6.7 server.

I have disables iptables, firewalls, and CHAP authentication on the target, so none of that should be an issue. AFAIK I'm running the latest version of open-iscsi on both boxes.

Any ideas what I can do from here ? If you need more information out of me, just ask.

--
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.
ZER0SEN | 11 Mar 20:42 2016
Picon

NoPortalsFound

Hi all,

I'm setting up a little test network and am trying to connect my server (control) to my storage (NAS)  via iSCSI. I'm having a little issue getting my initiator to see my target.

When I attempt to discover my target, all I get is :

root <at> control:/home/Administrator# iscsiadm -m discovery -t st -p 192.168.122.9
iscsiadm: No portals found

Both machines can ping, and control can see port 3260 as open according to nmap :

root <at> control:/home/Administrator# nmap 192.168.122.9

Starting Nmap 6.00 ( http://nmap.org ) at 2016-03-11 11:35 AST
Nmap scan report for NAS.seamine.local (192.168.122.9)
Host is up (0.000084s latency).
Not shown: 995 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
111/tcp   open  rpcbind
3260/tcp  open  iscsi <-------
6000/tcp  open  X11
10000/tcp open  snet-sensor-mgmt
MAC Address: 00:24:E8:10:EF:82 (Dell)

Nmap done: 1 IP address (1 host up) scanned in 0.61 seconds

Interestingly, if I only type iscsiadm -m discovery i can see the NAS, but not the actual target :

root <at> control:/home/Administrator# iscsiadm -m discovery
NAS.seamine.local:3260 via sendtargets
192.168.122.9:3260 via sendtargets

So, everything seems like it should be go to me, but obviously I'm missing something.

Thus far I have disabled all firewalls and iptables services on both machines. I have not enabled CHAP on the target at all. I inputted control's ip so the target would recognize it in case that was an issue. I originally did not set this to leave it open.

In fact, here is the target config :

<target iqn.2016-03.seamine.local:target00>
 backing-store /iscsi_disks/disk01.img
 initiator-address 192.168.122.1
 initiator-name 192.168.122.1
</target>

The only other thing I can think of to say is control is running Univention 4.1 (which is basically Debian) and NAS is a CentOS 6.7 machine. I am running the latest open-iscsi version on both.

Any insights you may have would be appreciated at this point. If there is any more information I can get you, don't hesitate to ask for it !

-G

--
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.
Picon

iscsi daemon in docker container

Hello,

As per Michael Christie suggestion, I am reaching out to a wider audience.  I am trying to run iscsid inside of
a Docker container but without using systemd. When I start iscsid -d 8 -f, it fails with "Cannot bind IPC
socket". I would appreciate if somebody who managed to get it working, share his/her steps.

Thank you

Serguei

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Lars Schimmer | 8 Mar 14:49 2016
Picon

Issues on debian jessie and Dell MD3200i - connection pdu rejected

Hi!

We jsut upgraded one of our old wheezy linux server to Debian jessie.
Now Open-iscsi spits out this error on load:

 connection1:0: pdu (op 0x1 itt 0x33) rejected. Reason code 0x5
[  649.368791]  connection1:0: pdu (op 0x1 itt 0x1) rejected. Reason
code 0x5
[  649.368928]  connection1:0: pdu (op 0x1 itt 0x50) rejected. Reason
code 0x5
[  748.430030]  connection1:0: detected conn error (1020)
[  754.695618]  connection1:0: detected conn error (1021)

and the co9nnection is broken.
Any idea what could be the reason?

Thank you.

(the storage I connect to is a Dell MD3200i storage, no issues before of
this kind).

MfG,
Lars Schimmer
-- 
-------------------------------------------------------------
TU Graz, Institut für ComputerGraphik & WissensVisualisierung
Tel: +43 316 873-5405       E-Mail: l.schimmer@...
Fax: +43 316 873-5402       PGP-Key-ID: 0x4A9B1723

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.
Chris Leech | 4 Mar 01:09 2016
Picon

possible data corruption with iscsi_tcp and dm-multipath

When using multipath with iscsi_tcp, there may be the possibility of
data corruption when failing requests between paths during a short
network interruption.

The situation looks like this.

  1. A write is being sent on pathA, and the data is in the TCP transmit
     queue.

  2. The network connection for pathA is interrupted before the write
     data can be sent to the target.

  3. The connection error is detected, requests are failed, dm-multipath
     retires on pathB, iscsid calls ep_disconnect which for iscsi_tcp is
     a close().

  4. The write is successful on pathB

  5. The network connection for pathA is restored before TCP has given
     up on a graceful shutdown.

  6. The write that was started on pathA is completed, and then the FIN
     is sent to close the connection.

At [6] the network packet in the transmission queue held a pointer to
the data page, which may have changed so this stale write could be
carrying a completely incorrect payload.

Basically, if requests are being failed it's important to abort the TCP
connection rather than let TCP wait and attempt a graceful shutdown.

I'd really love to hear other opinions on this one. I don't have a solid trace
of this, but I'm working with a report of data corruption in a controlled test
setup that fits this.  I had the reporter try an early version of this patch,
that always set a 0 SO_LINGER time without the IN_LOGOUT check, and they no
longer could reproduce the problem.

Chris Leech (1):
  iscsi_tcp set SO_LINGER to abort connection for error handling

 usr/io.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

-- 
2.5.0

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Erez Zilber | 3 Mar 21:16 2016
Picon

iSCSI disconnections after running iscsistart

Hi,

I'm running iSCSI boot for RHEL & SUSE nodes. Sometimes, after
iscsistart is called, errors on the iSCSI target side occur (e.g. temp
network disconnection) and the iSCSI connection is disconnected. In
the boot log, it looks like this (on a RHEL node):

connection1:0: detected conn error (1020)

And then, of course, the node fails to boot.

I would expect that iscsid would handle this and reconnect, but I
don't see in the boot log that iscsid was started. I also took a look
at /usr/share/dracut/modules.d/95iscsi/iscsiroot, but didn't find
iscsid there.

Is it possible to run iscsid as part of initrd, before iscsistart is executed?

Thanks,
Erez

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

adheer.chandravanshi | 2 Mar 09:04 2016

[PATCH] iscsi tools: Add support for some host statistics

From: Adheer Chandravanshi <adheer.chandravanshi@...>

Add support to maintain and show some host statistics in iscsid.
This provides following host specific stats:
	iscsi_login_accept_rsps
	iscsi_login_other_fail_rsps
	iscsi_login_negotiate_fails
	iscsi_login_authenticate_fails
	iscsi_login_auth_fail_rsps
	iscsi_login_redirect_rsps
	iscsi_logout_normals
	iscsi_logout_others
	iscsi_connection_timeout_errors
	iscsi_session_failures

Signed-off-by: Adheer Chandravanshi <adheer.chandravanshi@...>
---
 include/iscsi_if.h     |   1 +
 usr/discovery.c        |  32 +++++++++-
 usr/event_poll.c       |  12 +++-
 usr/event_poll.h       |   3 +-
 usr/host.c             |  45 ++++++++++++++
 usr/host.h             |  14 +++++
 usr/initiator.c        | 100 +++++++++++++++++++++++++-----
 usr/initiator.h        |  16 ++++-
 usr/initiator_common.c | 162 ++++++++++++++++++++++++++++++++++++++++++++-----
 usr/iscsiadm.c         |  25 +++++---
 usr/iscsid.c           |  12 +++-
 usr/iscsistart.c       |  10 ++-
 usr/mgmt_ipc.c         |  19 ++++++
 usr/mgmt_ipc.h         |   9 +++
 usr/netlink.c          |   3 +-
 usr/transport.c        |   1 +
 usr/transport.h        |   1 +
 17 files changed, 416 insertions(+), 49 deletions(-)

diff --git a/include/iscsi_if.h b/include/iscsi_if.h
index 9d15811..0576dfb 100644
--- a/include/iscsi_if.h
+++ b/include/iscsi_if.h
 <at>  <at>  -536,6 +536,7  <at>  <at>  enum iscsi_err {
 	ISCSI_ERR_XMIT_FAILED		= ISCSI_ERR_BASE + 19,
 	ISCSI_ERR_TCP_CONN_CLOSE	= ISCSI_ERR_BASE + 20,
 	ISCSI_ERR_SCSI_EH_SESSION_RST	= ISCSI_ERR_BASE + 21,
+	ISCSI_ERR_NOP_TIMEDOUT		= ISCSI_ERR_BASE + 22,
 };

 /*
diff --git a/usr/discovery.c b/usr/discovery.c
index 593d226..4d23381 100644
--- a/usr/discovery.c
+++ b/usr/discovery.c
 <at>  <at>  -1060,6 +1060,11  <at>  <at>  done:
 		conn->socket_fd = -1;
 	}
 	session->id = -1;
+
+	if (session->host) {
+		iscsi_host_put(session->host);
+		session->host = NULL;
+	}
 }

 static int iscsi_create_leading_conn(struct iscsi_session *session)
 <at>  <at>  -1104,7 +1109,15  <at>  <at>  static int iscsi_create_leading_conn(struct iscsi_session *session)
 		 * if offload is used.
 		 */
 		session->conn[0].bind_ep = 1;
-		session->hostno = host_no;
+		/*
+		 * some offload functions need the host so create now for
+		 * them
+		 */
+		session->host = iscsi_host_create(host_no);
+		if (!session->host) {
+			rc = ISCSI_ERR_NOMEM;
+			goto close_ipc;
+		}
 	}

 	rc = iscsi_host_set_net_params(iface, session);
 <at>  <at>  -1113,7 +1126,7  <at>  <at>  static int iscsi_create_leading_conn(struct iscsi_session *session)
 			  rc);
 		if (rc != ISCSI_ERR_AGAIN)
 			rc = ISCSI_ERR_INTERNAL;
-		goto close_ipc;
+		goto free_host;
 	}

 	/* create interconnect endpoint */
 <at>  <at>  -1121,7 +1134,7  <at>  <at>  static int iscsi_create_leading_conn(struct iscsi_session *session)
 	rc = t->template->ep_connect(conn, 1);
 	if (rc < 0) {
 		rc = ISCSI_ERR_TRANS;
-		goto close_ipc;
+		goto free_host;
 	}

 	do {
 <at>  <at>  -1150,6 +1163,15  <at>  <at>  static int iscsi_create_leading_conn(struct iscsi_session *session)
 		rc = ISCSI_ERR_INTERNAL;
 		goto disconnect;
 	}
+
+	if (!session->host) {
+		session->host = iscsi_host_create(host_no);
+		if (!session->host) {
+			rc = ISCSI_ERR_NOMEM;
+			goto disconnect;
+		}
+	}
+
 	log_debug(2, "%s discovery created session %u", __FUNCTION__,
 		  session->id);
 	session->isid[3] = (session->id >> 16) & 0xff;
 <at>  <at>  -1196,6 +1218,10  <at>  <at>  disconnect:
 		session->id = -1;
 	}

+free_host:
+	iscsi_host_put(session->host);
+	session->host = NULL;
+
 close_ipc:
 	if (conn->socket_fd >= 0) {
 		ipc->ctldev_close();
diff --git a/usr/event_poll.c b/usr/event_poll.c
index 209ee02..52391db 100644
--- a/usr/event_poll.c
+++ b/usr/event_poll.c
 <at>  <at>  -38,6 +38,7  <at>  <at> 
 #include "actor.h"
 #include "initiator.h"
 #include "iscsi_err.h"
+#include "host.h"

 static unsigned int reap_count;

 <at>  <at>  -121,7 +122,8  <at>  <at>  static int shutdown_wait_pids(void)
 #define POLL_CTRL	0
 #define POLL_IPC	1
 #define POLL_ALARM	2
-#define POLL_MAX	3
+#define POLL_UDEV	3
+#define POLL_MAX	4

 static int event_loop_stop;
 static queue_task_t *shutdown_qtask; 
 <at>  <at>  -132,7 +134,8  <at>  <at>  void event_loop_exit(queue_task_t *qtask)
 	event_loop_stop = 1;
 }

-void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd)
+void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd,
+		int udev_fd)
 {
 	struct pollfd poll_array[POLL_MAX];
 	int res, has_shutdown_children = 0;
 <at>  <at>  -156,6 +159,8  <at>  <at>  void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd)
 	poll_array[POLL_IPC].events = POLLIN;
 	poll_array[POLL_ALARM].fd = sig_fd;
 	poll_array[POLL_ALARM].events = POLLIN;
+	poll_array[POLL_UDEV].fd = udev_fd;
+	poll_array[POLL_UDEV].events = POLLIN;

 	event_loop_stop = 0;
 	while (1) {
 <at>  <at>  -192,6 +197,9  <at>  <at>  void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd)
 					log_debug(1, "Poll was woken by an alarm");
 				}
 			}
+
+			if (poll_array[POLL_UDEV].revents)
+				udev_event_handle(udev_fd);
 		} else if (res < 0) {
 			if (errno == EINTR) {
 				log_debug(1, "event_loop interrupted");
diff --git a/usr/event_poll.h b/usr/event_poll.h
index c0eed5c..0a7ed7c 100644
--- a/usr/event_poll.h
+++ b/usr/event_poll.h
 <at>  <at>  -25,7 +25,8  <at>  <at>  struct queue_task;
 int shutdown_callback(pid_t pid);
 void reap_proc(void);
 void reap_inc(void);
-void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd);
+void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd,
+		int udev_fd);
 void event_loop_exit(struct queue_task *qtask);

 #endif
diff --git a/usr/host.c b/usr/host.c
index f2052d3..b0dc914 100644
--- a/usr/host.c
+++ b/usr/host.c
 <at>  <at>  -35,6 +35,9  <at>  <at> 
 #include "iface.h"
 #include "iscsi_err.h"
 #include "iscsi_netlink.h"
+#include "iscsid_req.h"
+
+LIST_HEAD(iscsi_host);

 static int match_host_to_session(void *data, struct session_info *info)
 {
 <at>  <at>  -424,3 +427,45  <at>  <at>  int chap_build_config(struct iscsi_chap_rec *crec, struct iovec *iovs)

 	return count;
 }
+
+int host_print_login_stats(int host_no)
+{
+	int rc;
+	iscsiadm_req_t req;
+	iscsiadm_rsp_t rsp;
+	struct iscsi_login_stats *stats;
+
+	memset(&req, 0, sizeof(req));
+	req.command = MGMT_IPC_HOST_STATS;
+	req.u.host_login_stats.host_no = host_no;
+
+	rc = iscsid_exec_req(&req, &rsp, 1);
+	if (rc)
+		return rc;
+
+	stats = &rsp.u.host_login_stats.stats;
+
+	printf("Host Login Statistics:\n"
+		"\tiscsi_login_accept_rsps: %llu\n"
+		"\tiscsi_login_other_fail_rsps: %llu\n"
+		"\tiscsi_login_negotiate_fails: %llu\n"
+		"\tiscsi_login_authenticate_fails: %llu\n"
+		"\tiscsi_login_auth_fail_rsps: %llu\n"
+		"\tiscsi_login_redirect_rsps: %llu\n"
+		"\tiscsi_logout_normals: %llu\n"
+		"\tiscsi_logout_others: %llu\n"
+		"\tiscsi_connection_timeout_errors: %llu\n"
+		"\tiscsi_session_failures: %llu\n",
+		(unsigned long long)stats->login_accept_rsps,
+		(unsigned long long)stats->login_other_fail_rsps,
+		(unsigned long long)stats->login_negotiate_fails,
+		(unsigned long long)stats->login_authenticate_fails,
+		(unsigned long long)stats->login_auth_fail_rsps,
+		(unsigned long long)stats->login_redirect_rsps,
+		(unsigned long long)stats->logout_normals,
+		(unsigned long long)stats->logout_others,
+		(unsigned long long)stats->connection_timeout_errors,
+		(unsigned long long)stats->session_failures);
+
+	return 0;
+}
diff --git a/usr/host.h b/usr/host.h
index 149aa0d..1a16db7 100644
--- a/usr/host.h
+++ b/usr/host.h
 <at>  <at>  -16,7 +16,21  <at>  <at>  struct host_info {
         uint32_t host_no;
 };

+struct iscsi_login_stats {
+	uint64_t login_accept_rsps;
+	uint64_t login_other_fail_rsps;
+	uint64_t login_negotiate_fails;
+	uint64_t login_authenticate_fails;
+	uint64_t login_auth_fail_rsps;
+	uint64_t login_redirect_rsps;
+	uint64_t logout_normals;
+	uint64_t logout_others;
+	uint64_t connection_timeout_errors;
+	uint64_t session_failures;
+};
+
 extern int host_info_print(int info_level, uint32_t host_no);
 extern int chap_build_config(struct iscsi_chap_rec *crec, struct iovec *iovs);
+extern int host_print_login_stats(int host_no);

 #endif
diff --git a/usr/initiator.c b/usr/initiator.c
index 8cd1896..24f9368 100644
--- a/usr/initiator.c
+++ b/usr/initiator.c
 <at>  <at>  -142,6 +142,7  <at>  <at>  static void iscsi_ev_context_put(struct iscsi_ev_context *ev_context)
 	ev_context->allocated = 0;
 }

+
 static void session_online_devs(int host_no, int sid)
 {
 	iscsi_sysfs_for_each_device(NULL, host_no, sid,
 <at>  <at>  -152,14 +153,18  <at>  <at>  static conn_login_status_e
 __login_response_status(iscsi_conn_t *conn,
 		      enum iscsi_login_status login_status)
 {
+	struct iscsi_login_stats *stats = &conn->session->host->login_stats;
+
 	switch (login_status) {
 	case LOGIN_OK:
 		/* check the status class and detail */
 		return CONN_LOGIN_SUCCESS;
 	case LOGIN_REDIRECT:
+		stats->login_redirect_rsps++;
 		return CONN_LOGIN_IMM_REDIRECT_RETRY;
 	case LOGIN_IO_ERROR:
 	case LOGIN_REDIRECTION_FAILED:
+		stats->login_other_fail_rsps++;
 		return CONN_LOGIN_RETRY;
 	default:
 		log_error("Login error (Login status %d) on conn %d", conn->id,
 <at>  <at>  -175,11 +180,15  <at>  <at>  __check_iscsi_status_class(iscsi_session_t *session, int cid,
 			uint8_t status_class, uint8_t status_detail)
 {
 	iscsi_conn_t *conn = &session->conn[cid];
+	struct iscsi_login_stats *stats = &session->host->login_stats;

 	switch (status_class) {
 	case ISCSI_STATUS_CLS_SUCCESS:
+		stats->login_accept_rsps++;
 		return CONN_LOGIN_SUCCESS;
 	case ISCSI_STATUS_CLS_REDIRECT:
+		stats->login_redirect_rsps++;
+
 		switch (status_detail) {
 		case ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP:
 			return CONN_LOGIN_IMM_RETRY;
 <at>  <at>  -204,15 +213,18  <at>  <at>  __check_iscsi_status_class(iscsi_session_t *session, int cid,
 			log_error("session %d login rejected: Initiator "
 			       "failed authentication with target",
 				session->id);
+			stats->login_auth_fail_rsps++;
 			return CONN_LOGIN_AUTH_FAILED;
 		case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN:
 			log_error("conn %d login rejected: initiator "
 			       "failed authorization with target", conn->id);
+			stats->login_authenticate_fails++;
 			return CONN_LOGIN_AUTH_FAILED;
 		case ISCSI_LOGIN_STATUS_TGT_NOT_FOUND:
 			log_error("conn %d login rejected: initiator "
 			       "error - target not found (%02x/%02x)",
 			       conn->id, status_class, status_detail);
+			stats->login_other_fail_rsps++;
 			return CONN_LOGIN_FAILED;
 		case ISCSI_LOGIN_STATUS_NO_VERSION:
 			/*
 <at>  <at>  -224,16 +236,30  <at>  <at>  __check_iscsi_status_class(iscsi_session_t *session, int cid,
 			       "version (%02x/%02x), non-retryable, "
 			       "giving up", conn->id, status_class,
 			       status_detail);
+			stats->login_other_fail_rsps++;
+			return CONN_LOGIN_FAILED;
+		case ISCSI_LOGIN_STATUS_TGT_REMOVED:
+			log_error("conn %d login rejected: target removed "
+				  "(%02x/%02x)", conn->id, status_class,
+				  status_detail);
+			stats->login_negotiate_fails++;
+		case ISCSI_LOGIN_STATUS_MISSING_FIELDS:
+			log_error("conn %d login rejected: missing parameters "
+				  "(%02x/%02x)", conn->id, status_class,
+				  status_detail);
+			stats->login_negotiate_fails++;
 			return CONN_LOGIN_FAILED;
 		default:
 			log_error("conn %d login rejected: initiator "
-			       "error (%02x/%02x)", conn->id, status_class,
-			       status_detail);
+				  "error (%02x/%02x)", conn->id, status_class,
+				  status_detail);
+			stats->login_other_fail_rsps++;
 			return CONN_LOGIN_FAILED;
 		}
 	case ISCSI_STATUS_CLS_TARGET_ERR:
 		log_error("conn %d login rejected: target error "
 		       "(%02x/%02x)", conn->id, status_class, status_detail);
+		stats->login_other_fail_rsps++;
 		/*
 		 * We have no idea what the problem is. But spec says initiator
 		 * may retry later.
 <at>  <at>  -243,6 +269,7  <at>  <at>  __check_iscsi_status_class(iscsi_session_t *session, int cid,
 		log_error("conn %d login response with unknown status "
 		       "class 0x%x, detail 0x%x", conn->id, status_class,
 		       status_detail);
+		stats->login_other_fail_rsps++;
 		break;
 	}

 <at>  <at>  -409,7 +436,11  <at>  <at>  __session_create(node_rec_t *rec, struct iscsi_transport *t, int *rc)
                          * if offload is used.
                          */
                         session->conn[0].bind_ep = 1;
-                        session->hostno = hostno;
+			session->host = iscsi_host_create(hostno);
+			if (!session->host) {
+				*rc = ISCSI_ERR_NOMEM;
+				goto free_session;
+			}
                 } else if (*rc == ISCSI_ERR_HOST_NOT_FOUND) {
                         goto free_session;	
                 } else {
 <at>  <at>  -447,6 +478,7  <at>  <at>  static void
 __session_destroy(iscsi_session_t *session)
 {
 	log_debug(1, "destroying session");
+	iscsi_host_put(session->host);
 	list_del(&session->list);
 	iscsi_flush_context_pool(session);
 	session_release(session);
 <at>  <at>  -871,11 +903,26  <at>  <at>  static void session_conn_error(void *data)

 	iscsi_ev_context_put(ev_context);

+	/*
+	 * kernel could return some errors before session and host is fully
+	 * setup
+	 */
+	if (session->host)
+		session->host->login_stats.session_failures++;
+
 	switch (error) {
 	case ISCSI_ERR_INVALID_HOST:
 		if (session_conn_shutdown(conn, NULL, ISCSI_SUCCESS))
 			log_error("BUG: Could not shutdown session.");
 		break;
+	case ISCSI_ERR_NOP_TIMEDOUT:
+	case ISCSI_ERR_SCSI_EH_SESSION_RST:
+		/*
+		 * Connection/session was dropped due to scsi command, TMF, or
+		 * Nop-as-ping timing out.
+		 */
+		session->host->login_stats.connection_timeout_errors++;
+		/* fall through */
 	default:
 		__conn_error_handle(session, conn);
 	}
 <at>  <at>  -1048,7 +1095,8  <at>  <at>  setup_full_feature_phase(iscsi_conn_t *conn)
 		 * don't want to re-scan it on recovery.
 		 */
 		if (conn->id == 0)
-			session_scan_host(session, session->hostno, c->qtask);
+			session_scan_host(session, session->host->host_no,
+					  c->qtask);

 		log_warning("Connection%d:%d to [target: %s, portal: %s,%d] "
 			    "through [iface: %s] is operational now",
 <at>  <at>  -1059,7 +1107,7  <at>  <at>  setup_full_feature_phase(iscsi_conn_t *conn)
 	} else {
 		session->notify_qtask = NULL;

-		session_online_devs(session->hostno, session->id);
+		session_online_devs(session->host->host_no, session->id);
 		mgmt_ipc_write_rsp(c->qtask, ISCSI_SUCCESS);
 		log_warning("connection%d:%d is operational after recovery "
 			    "(%d attempts)", session->id, conn->id,
 <at>  <at>  -1170,6 +1218,7  <at>  <at>  static void iscsi_recv_nop_in(iscsi_conn_t *conn, struct iscsi_hdr *hdr)
 static void iscsi_recv_logout_rsp(iscsi_conn_t *conn, struct iscsi_hdr *hdr)
 {
 	struct iscsi_logout_rsp *logout_rsp = (struct iscsi_logout_rsp *)hdr;
+	iscsi_session_t *session = conn->session;

 	log_debug(3, "Recv: logout response %d", logout_rsp->response);
 	if (logout_rsp->response == 2 || logout_rsp->response == 3) {
 <at>  <at>  -1177,6 +1226,12  <at>  <at>  static void iscsi_recv_logout_rsp(iscsi_conn_t *conn, struct iscsi_hdr *hdr)
 		log_debug(4, "logout rsp returned time2wait %u",
 			  conn->session->def_time2wait);
 	}
+
+	if (!logout_rsp->response)
+		session->host->login_stats.logout_normals++;
+	else
+		session->host->login_stats.logout_others++;
+
 	/* TODO process the hdr */
 	__conn_error_handle(conn->session, conn);
 }
 <at>  <at>  -1203,7 +1258,8  <at>  <at>  static void iscsi_recv_async_msg(iscsi_conn_t *conn, struct iscsi_hdr *hdr)
 		}

 		if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
-			session_scan_host(session, session->hostno, NULL);
+			session_scan_host(session, session->host->host_no,
+					  NULL);
 		break;
 	case ISCSI_ASYNC_MSG_REQUEST_LOGOUT:
 		log_warning("Target requests logout within %u seconds for "
 <at>  <at>  -1242,8 +1298,11  <at>  <at>  static void iscsi_recv_login_rsp(struct iscsi_conn *conn)
 	struct iscsi_session *session = conn->session;
 	iscsi_login_context_t *c = &conn->login_context;
 	int err = ISCSI_ERR_FATAL_LOGIN;
+	struct iscsi_login_stats *stats = &session->host->login_stats;

-	if (iscsi_login_rsp(session, c)) {
+	if (!iscsi_login_rsp(session, c)) {
+		stats->login_accept_rsps++;
+	} else {
 		log_debug(1, "login_rsp ret (%d)", c->ret);

 		switch (__login_response_status(conn, c->ret)) {
 <at>  <at>  -1418,7 +1477,7  <at>  <at>  static void session_increase_wq_priority(struct iscsi_session *session)
 		*proc_name_end = '\0';

 		if (sscanf(proc_name, "iscsi_q_%u\n", &host_no) == 1) {
-			if (host_no == session->hostno) {
+			if (host_no == session->host->host_no) {
 				if (!setpriority(PRIO_PROCESS, pid,
 					session->nrec.session.xmit_thread_priority)) {
 					closedir(proc_dir);
 <at>  <at>  -1462,9 +1521,16  <at>  <at>  retry_create:
 	}

 	if (!err) {
-		session->hostno = host_no;
+		if (!session->host) {
+			session->host = iscsi_host_create(host_no);
+			if (!session->host) {
+				/* caller will destroy session for us */
+				return -ENOMEM;
+			}
+		}
 		session_increase_wq_priority(session);
 	}
+
 	return err;
 }

 <at>  <at>  -1536,6 +1602,7  <at>  <at>  static void session_conn_poll(void *data)
 			iscsi_login_eh(conn, qtask, ISCSI_ERR_INTERNAL);
 			return;
 		}
+
 		ev_context->data = qtask;
 		/* not connected yet, check later */
 		iscsi_sched_ev_context(ev_context, conn, 1, EV_CONN_POLL);
 <at>  <at>  -1550,8 +1617,8  <at>  <at>  static void session_conn_poll(void *data)
 				err = ISCSI_ERR_INTERNAL;
 				goto cleanup;
 			}
-			log_debug(3, "created new iSCSI session sid %d host "
-				  "no %u", session->id, session->hostno);
+			log_debug(3, "created new iSCSI session sid %d host %u",
+				  session->id, session->host->host_no);

 			err = ipc->create_conn(session->t->handle,
 					session->id, conn->id, &conn->id);
 <at>  <at>  -1656,7 +1723,7  <at>  <at>  static void session_conn_process_login(void *data)
 	 * logged in
 	 */
 	log_debug(3, "session created sid %u host no %d", session->id,
-		  session->hostno);
+		  session->host->host_no);

 	if (session->r_stage == R_STAGE_NO_CHANGE ||
 	    session->r_stage == R_STAGE_SESSION_REDIRECT) {
 <at>  <at>  -1664,7 +1731,7  <at>  <at>  static void session_conn_process_login(void *data)
 		 * scan host is one-time deal. We
 		 * don't want to re-scan it on recovery.
 		 */
-		session_scan_host(session, session->hostno,
+		session_scan_host(session, session->host->host_no,
 				 c->qtask);
 		session->notify_qtask = NULL;

 <at>  <at>  -1995,6 +2062,7  <at>  <at>  iscsi_sync_session(node_rec_t *rec, queue_task_t *qtask, uint32_t sid)
 {
 	iscsi_session_t *session;
 	struct iscsi_transport *t;
+	uint32_t hostno;
 	int err;

 	t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name);
 <at>  <at>  -2006,12 +2074,16  <at>  <at>  iscsi_sync_session(node_rec_t *rec, queue_task_t *qtask, uint32_t sid)
 		return ISCSI_ERR_LOGIN;

 	session->id = sid;
-	session->hostno = iscsi_sysfs_get_host_no_from_sid(sid, &err);
+	hostno = iscsi_sysfs_get_host_no_from_sid(sid, &err);
 	if (err) {
 		log_error("Could not get hostno for session %d", sid);
 		goto destroy_session;
 	}

+	session->host = iscsi_host_create(hostno);
+	if (!session->host)
+		goto destroy_session;
+
 	session->r_stage = R_STAGE_SESSION_REOPEN;

 	err = sync_conn(session, 0);
diff --git a/usr/initiator.h b/usr/initiator.h
index c11d77f..ca0a191 100644
--- a/usr/initiator.h
+++ b/usr/initiator.h
 <at>  <at>  -32,6 +32,7  <at>  <at> 
 #include "config.h"
 #include "actor.h"
 #include "list.h"
+#include "host.h"

 #define ISCSI_CONFIG_ROOT	"/etc/iscsi/"

 <at>  <at>  -191,6 +192,13  <at>  <at>  typedef struct queue_task {
 	void *payload;
 } queue_task_t;

+struct iscsi_host {
+	struct iscsi_login_stats login_stats;
+	uint32_t host_no;
+	uint32_t ref_count;
+	struct list_head list;
+};
+
 struct iscsi_transport_template;
 struct iscsi_transport;

 <at>  <at>  -198,7 +206,7  <at>  <at>  struct iscsi_transport;
 typedef struct iscsi_session {
 	struct list_head list;
 	uint32_t id;
-	uint32_t hostno;
+	struct iscsi_host *host;
 	char netdev[IFNAMSIZ];
 	struct iscsi_transport *t;
 	uint8_t use_ipc;
 <at>  <at>  -359,4 +367,10  <at>  <at>  extern int iscsi_set_net_config(struct iscsi_transport *t,
 				struct iface_rec *iface);
 extern void iscsi_session_init_params(struct iscsi_session *session);

+/* initiator host code */
+extern struct iscsi_host *iscsi_host_find_by_host_no(uint32_t host_no);
+extern void iscsi_host_put(struct iscsi_host *host);
+extern struct iscsi_host *iscsi_host_create(uint32_t host_no);
+extern int udev_event_listen(void);
+extern void udev_event_handle(int udev_fd);
 #endif /* INITIATOR_H */
diff --git a/usr/initiator_common.c b/usr/initiator_common.c
index c02643a..e040bde 100644
--- a/usr/initiator_common.c
+++ b/usr/initiator_common.c
 <at>  <at>  -23,6 +23,10  <at>  <at> 
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>

 #include "initiator.h"
 #include "transport.h"
 <at>  <at>  -37,6 +41,143  <at>  <at> 
 #include "iscsi_err.h"
 #include "iscsi_net_util.h"

+#define UEVENT_BUFFER_SIZE	2048
+
+static LIST_HEAD(iscsi_hosts);
+
+struct iscsi_host *iscsi_host_find_by_host_no(uint32_t host_no)
+{
+	struct iscsi_host *host;
+
+	list_for_each_entry(host, &iscsi_hosts, list) {
+		if (host->host_no == host_no) {
+			log_debug(7, "Found iSCSI host %d\n", host->host_no);
+			return host;
+		}
+	}
+
+	log_debug(7, "iSCSI host %d not found\n", host->host_no);
+	return NULL;
+}
+
+static void iscsi_host_get(struct iscsi_host *host)
+{
+	host->ref_count++;
+}
+
+#define SCSI_HOST_SUBSYS                "scsi_host"
+void iscsi_host_put(struct iscsi_host *host)
+{
+	char id[NAME_SIZE];
+	char devpath[PATH_SIZE];
+
+	if (!host)
+		return;
+
+	snprintf(id, sizeof(id), "host%u", host->host_no);
+
+	/* For sotware iSCSI if all sessions are logout, sysfs host will be
+	 * destroyed and we will not get devpath */
+	if (!sysfs_lookup_devpath_by_subsys_id(devpath, sizeof(devpath),
+					       SCSI_HOST_SUBSYS, id)) {
+		log_error("Could not lookup devpath for %s.\n", id);
+		goto free_host;
+	}
+
+	/* If we have valid host path, its offload iSCSI do not destroy host */
+	return;
+free_host:
+	host->ref_count--;
+	if (!host->ref_count) {
+		log_debug(1, "free %s\n", id);
+		list_del(&host->list);
+		free(host);
+	}
+}
+
+void iscsi_offload_host_put(uint32_t host_no)
+{
+	struct iscsi_host *host = iscsi_host_find_by_host_no(host_no);
+
+	if (!host)
+		return;
+
+	log_debug(1, "free host%u\n", host->host_no);
+	list_del(&host->list);
+	free(host);
+}
+
+struct iscsi_host *iscsi_host_create(uint32_t host_no)
+{
+	struct iscsi_host *host = iscsi_host_find_by_host_no(host_no);
+
+	if (!host) {
+		host = calloc(1, sizeof(*host));
+		if (!host)
+			return NULL;
+		host->host_no = host_no;
+		INIT_LIST_HEAD(&host->list);
+		list_add_tail(&host->list, &iscsi_hosts);
+	}
+
+	iscsi_host_get(host);
+	return host;
+}
+
+int udev_event_listen(void)
+{
+	int udev_fd = -1;
+	int ret = -1;
+	struct sockaddr_nl snl;
+
+	bzero(&snl, sizeof(struct sockaddr_nl));
+	snl.nl_family = AF_NETLINK;
+	snl.nl_pid = getpid();
+	snl.nl_groups = 1;
+
+	udev_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+	if (udev_fd < 0) {
+		log_error("Can not create udev event socket\n");
+		return udev_fd;
+	}
+
+	ret = bind(udev_fd, (struct sockaddr *)&snl,
+		   sizeof(struct sockaddr_nl));
+	if (ret < 0) {
+		log_error("Can not bind udev event socket\n");
+		close(udev_fd);
+		return ret;
+	}
+
+	return udev_fd;
+}
+
+void udev_event_handle(int udev_fd)
+{
+	char buf[UEVENT_BUFFER_SIZE] = {0};
+	char *tmp_buf1, *tmp_buf2;
+	char *pos;
+	uint32_t host_no;
+
+	memset(buf, 0, sizeof(buf));
+	recv(udev_fd, &buf, sizeof(buf), 0);
+
+	tmp_buf1 = strstr(buf, "remove");
+	if (tmp_buf1 == NULL)
+		return;
+
+	tmp_buf2 = strstr(tmp_buf1, "iscsi_host");
+	if (tmp_buf2 == NULL)
+		return;
+
+	pos = &tmp_buf2[strlen(tmp_buf2)];
+	while (isdigit(pos[-1]))
+		pos--;
+
+	host_no = atoi(pos);
+	iscsi_offload_host_put(host_no);
+}
+
 struct iscsi_session *session_find_by_sid(uint32_t sid)
 {
 	struct iscsi_transport *t;
 <at>  <at>  -299,7 +440,7  <at>  <at>  int iscsi_host_set_params(struct iscsi_session *session)
 	};

 	for (i = 0; i < MAX_HOST_PARAMS; i++) {
-		if (host_set_param(t, session->hostno,
+		if (host_set_param(t, session->host->host_no,
 				   hosttbl[i].param, hosttbl[i].value,
 				   hosttbl[i].type)) {
 			return EPERM;
 <at>  <at>  -631,20 +772,11  <at>  <at>  int iscsi_set_net_config(struct iscsi_transport *t, iscsi_session_t *session,
 	if (t->template->set_net_config) {
 		/* uip needs the netdev name */
 		struct host_info hinfo;
-		int hostno, rc;
-
-		/* this assumes that the netdev or hw address is going to be
-		   set */
-		hostno = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
-		if (rc) {
-			log_debug(4, "Couldn't get host no.");
-			return rc;
-		}

 		/* uip needs the netdev name */
 		if (!strlen(iface->netdev)) {
 			memset(&hinfo, 0, sizeof(hinfo));
-			hinfo.host_no = hostno;
+			hinfo.host_no = session->host->host_no;
 			iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);
 			strcpy(iface->netdev, hinfo.iface.netdev);
 		}
 <at>  <at>  -692,7 +824,7  <at>  <at>  int iscsi_host_set_net_params(struct iface_rec *iface,
 		netdev = iface->netdev;
 	else {
 		memset(&hinfo, 0, sizeof(hinfo));
-		hinfo.host_no = session->hostno;
+		hinfo.host_no = session->host->host_no;
 		iscsi_sysfs_get_hostinfo_by_host_no(&hinfo);

 		netdev = hinfo.iface.netdev;
 <at>  <at>  -706,14 +838,14  <at>  <at>  int iscsi_host_set_net_params(struct iface_rec *iface,
 	if (rc != 0)
 		return rc;

-	rc = host_set_param(t, session->hostno,
+	rc = host_set_param(t, session->host->host_no,
 			    ISCSI_HOST_PARAM_IPADDRESS,
 			    iface->ipaddress, ISCSI_STRING);
 	if (rc)
 		return rc;

 	if (iface_is_bound_by_netdev(iface)) {
-		rc = host_set_param(t, session->hostno,
+		rc = host_set_param(t, session->host->host_no,
 				    ISCSI_HOST_PARAM_NETDEV_NAME,
 				    iface->netdev, ISCSI_STRING);
 		if (rc)
 <at>  <at>  -721,7 +853,7  <at>  <at>  int iscsi_host_set_net_params(struct iface_rec *iface,
 	}

 	if (iface_is_bound_by_hwaddr(iface)) {
-		rc = host_set_param(t, session->hostno,
+		rc = host_set_param(t, session->host->host_no,
 				    ISCSI_HOST_PARAM_HWADDRESS,
 				    iface->hwaddress, ISCSI_STRING);
 		if (rc)
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index c6705bd..e06d8ef 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
 <at>  <at>  -2215,43 +2215,49  <at>  <at>  static int exec_host_stats_op(int op, int info_level, uint32_t host_no)
 	int rc = ISCSI_SUCCESS;
 	int fd = 0, buf_size = 0;

+	/* ignore error incase iscsid is not up */
+	host_print_login_stats(host_no);
+
 	t = iscsi_sysfs_get_transport_by_hba(host_no);
 	if (!t) {
 		log_error("Could not match hostno %u to transport.", host_no);
 		rc = ISCSI_ERR_TRANS_NOT_FOUND;
-		goto exit_host_stats;
+		goto done;
 	}

+	if (!t->template->offload_host_stats)
+		goto done;
+
 	buf_size = sizeof(struct iscsi_offload_host_stats) +
 		   sizeof(struct iscsi_uevent);
 	req_buf = calloc(1, buf_size);
 	if (!req_buf) {
 		log_error("Could not allocate memory for host stats request.");
 		rc = ISCSI_ERR_NOMEM;
-		goto exit_host_stats;
+		goto done;
 	}

 	fd = ipc->ctldev_open();
 	if (fd < 0) {
 		rc = ISCSI_ERR_INTERNAL;
 		log_error("Netlink open failed.");
-		goto exit_host_stats;
+		goto free_buf;
 	}

 	rc = ipc->get_host_stats(t->handle, host_no, req_buf);
 	if (rc < 0) {
-		log_error("get_host_stats failed. errno=%d", errno);
+		log_debug(7, "get_host_stats failed. errno=%d", errno);
 		rc = ISCSI_ERR;
-		goto exit_host_stats;
+	} else {
+		print_host_stats((struct iscsi_offload_host_stats *)(req_buf +
+				 sizeof(struct iscsi_uevent)));
 	}

-	print_host_stats((struct iscsi_offload_host_stats *)(req_buf +
-			 sizeof(struct iscsi_uevent)));
-
 	ipc->ctldev_close();

-exit_host_stats:
+free_buf:
 	free(req_buf);
+done:
 	return rc;
 }

 <at>  <at>  -3063,6 +3069,7  <at>  <at>  static uint64_t parse_host_info(char *optarg, int *rc)
 			*rc = ISCSI_ERR_INVAL;
 		}
 	} else {
+		errno = 0;
 		host_no = strtoull(optarg, NULL, 10);
 		if (errno || (host_no > MAX_HOST_NO)) {
 			if (host_no > MAX_HOST_NO)
diff --git a/usr/iscsid.c b/usr/iscsid.c
index f8ffd23..abbe16a 100644
--- a/usr/iscsid.c
+++ b/usr/iscsid.c
 <at>  <at>  -52,6 +52,7  <at>  <at> 
 #include "discoveryd.h"
 #include "iscsid_req.h"
 #include "iscsi_err.h"
+#include "host.h"

 /* global config info */
 struct iscsi_daemon_config daemon_config;
 <at>  <at>  -347,6 +348,7  <at>  <at>  int main(int argc, char *argv[])
 	struct sigaction sa_old;
 	struct sigaction sa_new;
 	int control_fd;
+	int udev_fd;
 	pid_t pid;

 	while ((ch = getopt_long(argc, argv, "c:i:fd:nu:g:p:vh", long_options,
 <at>  <at>  -413,6 +415,7  <at>  <at>  int main(int argc, char *argv[])

 	mgmt_ipc_fd = -1;
 	control_fd = -1;
+	udev_fd = -1;
 	daemon_config.initiator_name = NULL;
 	daemon_config.initiator_alias = NULL;

 <at>  <at>  -421,6 +424,12  <at>  <at>  int main(int argc, char *argv[])
 		exit(ISCSI_ERR);
 	}

+	udev_fd = udev_event_listen();
+	if (udev_fd < 0) {
+		log_close(log_pid);
+		exit(ISCSI_ERR);
+	}
+
 	if (daemonize) {
 		char buf[64];
 		int fd = -1;
 <at>  <at>  -554,12 +563,13  <at>  <at>  int main(int argc, char *argv[])
 		exit(ISCSI_ERR);
 	}

-	event_loop(ipc, control_fd, mgmt_ipc_fd);
+	event_loop(ipc, control_fd, mgmt_ipc_fd, udev_fd);

 	idbm_terminate();
 	sysfs_cleanup();
 	ipc->ctldev_close();
 	mgmt_ipc_close(mgmt_ipc_fd);
+	close(udev_fd);
 	if (daemon_config.initiator_name)
 		free(daemon_config.initiator_name);
 	if (daemon_config.initiator_alias)
diff --git a/usr/iscsistart.c b/usr/iscsistart.c
index 7ff2236..18a75d5 100644
--- a/usr/iscsistart.c
+++ b/usr/iscsistart.c
 <at>  <at>  -327,7 +327,7  <at>  <at>  int main(int argc, char *argv[])
 	struct boot_context *context, boot_context;
 	struct sigaction sa_old;
 	struct sigaction sa_new;
-	int control_fd, mgmt_ipc_fd, err;
+	int control_fd, mgmt_ipc_fd, udev_fd, err;
 	pid_t pid;

 	idbm_node_setup_defaults(&config_rec);
 <at>  <at>  -476,6 +476,12  <at>  <at>  int main(int argc, char *argv[])
 		exit(ISCSI_ERR_NOMEM);
 	}

+	udev_fd = udev_event_listen();
+	if (udev_fd < 0) {
+		log_error("Could not setup udev socket\n");
+		exit(ISCSI_ERR_NOMEM);
+	}
+
 	control_fd = ipc->ctldev_open();
 	if (control_fd < 0)
 		exit(ISCSI_ERR_NOMEM);
 <at>  <at>  -509,7 +515,7  <at>  <at>  int main(int argc, char *argv[])
 	 * Start Main Event Loop
 	 */
 	iscsi_initiator_init();
-	event_loop(ipc, control_fd, mgmt_ipc_fd);
+	event_loop(ipc, control_fd, mgmt_ipc_fd, udev_fd);
 	ipc->ctldev_close();
 	mgmt_ipc_close(mgmt_ipc_fd);
 	free_initiator();
diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c
index c16bce9..692e8ad 100644
--- a/usr/mgmt_ipc.c
+++ b/usr/mgmt_ipc.c
 <at>  <at>  -37,6 +37,7  <at>  <at> 
 #include "iscsi_ipc.h"
 #include "iscsi_err.h"
 #include "iscsi_util.h"
+#include "host.h"

 #define PEERUSER_MAX	64
 #define EXTMSG_MAX	(64 * 1024)
 <at>  <at>  -347,6 +348,23  <at>  <at>  mgmt_ipc_notify_del_portal(queue_task_t *qtask)
 }

 static int
+mgmt_ipc_host_get_login_stats(queue_task_t *qtask)
+{
+	uint32_t host_no = qtask->req.u.host_login_stats.host_no;
+	struct iscsi_host *host = iscsi_host_find_by_host_no(host_no);
+
+	if (host == NULL)
+		return ISCSI_ERR;
+
+	qtask->rsp.u.host_login_stats.host_no = host->host_no;
+	memcpy(&qtask->rsp.u.host_login_stats.stats, &host->login_stats,
+	       sizeof(struct iscsi_login_stats));
+	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+
+	return ISCSI_SUCCESS;
+}
+
+static int
 mgmt_peeruser(int sock, char *user)
 {
 #if defined(SO_PEERCRED)
 <at>  <at>  -530,6 +548,7  <at>  <at>  static mgmt_ipc_fn_t *	mgmt_ipc_functions[__MGMT_IPC_MAX_COMMAND] = {
 [MGMT_IPC_NOTIFY_DEL_NODE]	= mgmt_ipc_notify_del_node,
 [MGMT_IPC_NOTIFY_ADD_PORTAL]	= mgmt_ipc_notify_add_portal,
 [MGMT_IPC_NOTIFY_DEL_PORTAL]	= mgmt_ipc_notify_del_portal,
+[MGMT_IPC_HOST_STATS]		= mgmt_ipc_host_get_login_stats,
 };

 void mgmt_ipc_handle(int accept_fd)
diff --git a/usr/mgmt_ipc.h b/usr/mgmt_ipc.h
index 55972ed..0423f56 100644
--- a/usr/mgmt_ipc.h
+++ b/usr/mgmt_ipc.h
 <at>  <at>  -22,6 +22,7  <at>  <at> 
 #include "types.h"
 #include "iscsi_if.h"
 #include "config.h"
+#include "host.h"

 #define ISCSIADM_NAMESPACE	"ISCSIADM_ABSTRACT_NAMESPACE"
 #define PEERUSER_MAX		64
 <at>  <at>  -46,6 +47,7  <at>  <at>  typedef enum iscsiadm_cmd {
 	MGMT_IPC_NOTIFY_DEL_NODE	= 17,
 	MGMT_IPC_NOTIFY_ADD_PORTAL	= 18,
 	MGMT_IPC_NOTIFY_DEL_PORTAL	= 19,
+	MGMT_IPC_HOST_STATS		= 20,

 	__MGMT_IPC_MAX_COMMAND
 } iscsiadm_cmd_e;
 <at>  <at>  -77,6 +79,9  <at>  <at>  typedef struct iscsiadm_req {
 			char value[IFNAMSIZ + 1];

 		} set_host_param;
+		struct ipc_msg_host_login_stats {
+			int host_no;
+		} host_login_stats;
 	} u;
 } iscsiadm_req_t;

 <at>  <at>  -103,6 +108,10  <at>  <at>  typedef struct iscsiadm_rsp {
 			int session_state;
 			int conn_state;
 		} session_state;
+		struct ipc_msg_get_host_login_stats {
+			int host_no;
+			struct iscsi_login_stats stats;
+		} host_login_stats;
 	} u;
 } iscsiadm_rsp_t;

diff --git a/usr/netlink.c b/usr/netlink.c
index 2b85efe..d74f723 100644
--- a/usr/netlink.c
+++ b/usr/netlink.c
 <at>  <at>  -862,7 +862,8  <at>  <at>  ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking)
 	if (conn->bind_ep) {
 		ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST;
 		ev->u.ep_connect_through_host.non_blocking = non_blocking;
-		ev->u.ep_connect_through_host.host_no = conn->session->hostno;
+		ev->u.ep_connect_through_host.host_no =
+						conn->session->host->host_no;
 	} else {
 		ev->type = ISCSI_UEVENT_TRANSPORT_EP_CONNECT;
 		ev->u.ep_connect.non_blocking = non_blocking;
diff --git a/usr/transport.c b/usr/transport.c
index 18b7704..4797641 100644
--- a/usr/transport.c
+++ b/usr/transport.c
 <at>  <at>  -101,6 +101,7  <at>  <at>  struct iscsi_transport_template qla4xxx = {
 	.name		= "qla4xxx",
 	.set_host_ip	= SET_HOST_IP_NOT_REQ,
         .bind_ep_required = 1,
+	.offload_host_stats = 1,
 	.ep_connect	= ktransport_ep_connect,
 	.ep_poll	= ktransport_ep_poll,
 	.ep_disconnect	= ktransport_ep_disconnect,
diff --git a/usr/transport.h b/usr/transport.h
index 4d3bdbf..42bc3a5 100644
--- a/usr/transport.h
+++ b/usr/transport.h
 <at>  <at>  -39,6 +39,7  <at>  <at>  struct iscsi_transport_template {
 	uint8_t set_host_ip;
 	uint8_t use_boot_info;
         uint8_t bind_ep_required;
+	uint8_t offload_host_stats;
 	int (*ep_connect) (struct iscsi_conn *conn, int non_blocking);
 	int (*ep_poll) (struct iscsi_conn *conn, int timeout_ms);
 	void (*ep_disconnect) (struct iscsi_conn *conn);
-- 
1.8.5.2

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Chris Leech | 19 Feb 23:42 2016
Picon

persistant record layout and long DNS names

I was asked an interesting question recently, and thought I'd share it
here. I don't think it's critical to address right away, but surprising
and something to think about.

Someone asked me about targets configured to return DNS names rather
than IP addresses in a SendTargets response, and what the maximum length
of a response Open-iSCSI would accept was. Obviously they had tested
this and hit an issue or they wouldn't be asking.

It turns out that DNS names have a limit of 253 octets when converted to
a string. When we store a node record we append the port and tpgt as
part of the filename. That potentially takes up to 12 characters, two
16-bit values that might need 5 chars each + 2 commas. Basically all
Linux filesystems have a 255 byte filename limit, so any DNS name of
longer than 243 bytes (10 less than the DNS limit) will fail to create a
node record.

The discovery symlinks are much worse, as we try and put the target
name, address, port, tpgt, and iface name all together.

- Chris

--

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to open-iscsi+unsubscribe@...
To post to this group, send email to open-iscsi@...
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.


Gmane