<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
</head>
<body>
<br>
Thanks much, both of you.&nbsp; Ill take a look.<br>
<br>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> James Simmons &lt;jsimmons@infradead.org&gt;<br>
<b>Sent:</b> Wednesday, November 7, 2018 1:24:27 PM<br>
<b>To:</b> NeilBrown<br>
<b>Cc:</b> Patrick Farrell; Lustre Developement; James Simmons; sihara@whamcloud.com<br>
<b>Subject:</b> Re: Apparent bug in LU-8130 ptlrpc: convert conn_hash to rhashtable / Linux-commit: ac2370ac2bc5215daf78546cd8d925510065bb7f</font>
<div>&nbsp;</div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText"><br>
&gt; &gt; Neil, James,<br>
&gt; &gt;<br>
&gt; &gt; Sent this earlier, but with nasty formatting that got it rejected.&nbsp; Whoops.<br>
&gt; &gt; &nbsp;<br>
&gt; &gt; It looks like the patch we landed as:<br>
&gt; &gt; LU-8130 ptlrpc: convert conn_hash to rhashtable<br>
&gt; &gt; &nbsp;<br>
&gt; &gt; Linux has a resizeable hashtable implementation in lib,<br>
&gt; &gt; so we should use that instead of having one in libcfs.<br>
&gt; &gt; &nbsp;<br>
&gt; &gt; This patch converts the ptlrpc conn_hash to use rhashtable.<br>
&gt; &gt; In the process we gain lockless lookup.<br>
&gt; &gt; &nbsp;<br>
&gt; &gt; As connections are never deleted until the hash table is destroyed,<br>
&gt; &gt; there is no need to count the reference in the hash table. There<br>
&gt; &gt; is also no need to enable automatic_shrinking.<br>
&gt; &gt; &nbsp;<br>
&gt; &gt; Linux-commit: ac2370ac2bc5215daf78546cd8d925510065bb7f<br>
&gt; &gt; &nbsp;<br>
&gt; &gt; Introduced a bug.&nbsp; Ihara-san opened something to track it here:<br>
&gt; &gt; <a href="https://jira.whamcloud.com/browse/LU-11624">https://jira.whamcloud.com/browse/LU-11624</a><br>
&gt; &gt; &nbsp;<br>
&gt; &gt; Its a null pointer in nid_hash(); there are some more details at that link.<br>
&gt; <br>
&gt; That commit changed ptlrpc_connection_get() so that it can return NULL.<br>
&gt; <br>
&gt; This is actually one of the really annoying things about rhashtable.&nbsp; I<br>
&gt; cannot convince the maintainers that sometimes you need guaranteed<br>
&gt; success (which is quite possible with a hash table).&nbsp; They come from the<br>
&gt; networking community were they drop packets on errors all the time - no<br>
&gt; big deal.<br>
&gt; <br>
&gt; Anyway, all users of ptlrpc_connection_get() in the client code (in<br>
&gt; drivers/staging) test the return value against NULL, so this was safe.<br>
&gt; <br>
&gt; In SFS lustre, the call in target_handle_connect() assigned the<br>
&gt; result to export-&gt;exp_connection without checking against NULL.<br>
&gt; That leads to the oops.<br>
&gt; <br>
&gt; ptlrpc_connection_get() will return NULL when<br>
&gt; rhashtable_lookup_get_insert_fast() returns an error.<br>
&gt; The errors are mostly weird internal implementation details leaking out<br>
&gt; the API.&nbsp; A retry, possibly after a short delay, will usually succeed.<br>
&gt; (see <a href="https://lwn.net/Articles/751974/">https://lwn.net/Articles/751974/</a>, section &quot;Failure during insertion)<br>
&gt; If this happens a lot, it might suggest that the hash function is poor.<br>
&gt; <br>
&gt; Ahhhh... this was built against a 3.10 kernel.<br>
&gt; Prior to 4.6, hash_64() was not so much &quot;poor&quot; as &quot;appalling&quot;.<br>
&gt; See <a href="https://lwn.net/Articles/687494/">https://lwn.net/Articles/687494/</a><br>
&gt; <br>
&gt; For SFS we should avoid using hash_64() (at least before 4.6) and<br>
&gt; instead use something like<br>
&gt;&nbsp;&nbsp; hash_32((foo&gt;&gt;32) ^ hash_32(foo &amp; 0xFFFFFFFF))<br>
<br>
The libcfs hash is not much better :-( <br>
<br>
I have a purposed fix. Let me know if its correct. Thank you.<br>
<br>
>From 32df018c1af8fdbc833c537aafeea081ab3d8d7e Mon Sep 17 00:00:00 2001<br>
From: James Simmons &lt;uja.ornl@yahoo.com&gt;<br>
Date: Wed, 7 Nov 2018 14:06:37 -0500<br>
Subject: [PATCH] LU-11624 ptlrpc: handle no ptlrpc connection case<br>
<br>
With the move of ptlrpc connections hash to rhashtable it is now<br>
possible for ptlrpc_connection_get() to return NULL. The reason<br>
this can happen is due to conditions. One is that the hash has no<br>
more free slots which results in an E2BIG error. By default the<br>
maximum size for rhashtables is 2^31 so this is very unlikely<br>
going to happen. The second case returns a -ENOMEM which can<br>
happen when the bucket can be resized. For this case test the<br>
return value of rhashtable_lookup_get_insert_fast() and if it is<br>
-ENOMEM try again inserting the new connection into the hash<br>
table. Just as an extra level of protection against a failed<br>
connection attempt in target_handle_connect() exit out with<br>
-ENOTCONN.<br>
<br>
Change-Id: I0537564ba544ed06be42ba243606a884a1290f20<br>
Signed-off-by: James Simmons &lt;uja.ornl@yahoo.com&gt;<br>
---<br>
&nbsp;lustre/ldlm/ldlm_lib.c&nbsp;&nbsp;&nbsp;&nbsp; | 3 &#43;&#43;&#43;<br>
&nbsp;lustre/ptlrpc/connection.c | 6 &#43;&#43;&#43;&#43;&#43;-<br>
&nbsp;2 files changed, 8 insertions(&#43;), 1 deletion(-)<br>
<br>
diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c<br>
index de66aa3..463c6c6 100644<br>
--- a/lustre/ldlm/ldlm_lib.c<br>
&#43;&#43;&#43; b/lustre/ldlm/ldlm_lib.c<br>
@@ -1349,6 &#43;1349,9 @@ dont_check_exports:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; export-&gt;exp_connection = ptlrpc_connection_get(req-&gt;rq_peer,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; req-&gt;rq_self,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;cluuid);<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!export-&gt;exp_connection)<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GOTO(out, rc = -ENOTCONN);<br>
&#43;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (hlist_unhashed(&amp;export-&gt;exp_nid_hash))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cfs_hash_add(export-&gt;exp_obd-&gt;obd_nid_hash,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;export-&gt;exp_connection-&gt;c_peer.nid,<br>
diff --git a/lustre/ptlrpc/connection.c b/lustre/ptlrpc/connection.c<br>
index 21a24a2..045b3ee 100644<br>
--- a/lustre/ptlrpc/connection.c<br>
&#43;&#43;&#43; b/lustre/ptlrpc/connection.c<br>
@@ -103,13 &#43;103,17 @@ ptlrpc_connection_get(struct lnet_process_id peer, lnet_nid_t self,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * connection.&nbsp;&nbsp; The object which exists in the hash will be<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * returned,otherwise NULL is returned on success.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>
&#43;try_again:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn2 = rhashtable_lookup_get_insert_fast(&amp;conn_hash, &amp;conn-&gt;c_hash,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn_hash_params);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (conn2) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* insertion failed */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OBD_FREE_PTR(conn);<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (IS_ERR(conn2))<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (IS_ERR(conn2)) {<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (PTR_ERR(conn2) == -ENOMEM)<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto try_again;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = conn2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptlrpc_connection_addref(conn);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
-- <br>
1.8.3.1<br>
</div>
</span></font></div>
</body>
</html>