<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body>
<br>
Neil,<br>
<br>
So the semantics and behavior for a single bit bit lock and a mutex are the same?&nbsp; All the scheduler stuff, optimistic spin, etc?&nbsp; It may not matter here (probably not) but it makes me curious...<br>
<br>
- Patrick<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> lustre-devel &lt;lustre-devel-bounces@lists.lustre.org&gt; on behalf of NeilBrown &lt;neilb@suse.com&gt;<br>
<b>Sent:</b> Sunday, December 9, 2018 6:46:16 PM<br>
<b>To:</b> James Simmons; Oleg Drokin; Andreas Dilger<br>
<b>Cc:</b> Lustre Development List<br>
<b>Subject:</b> [lustre-devel] [PATCH 3/4] lustre: use bit-locking in echo_client.</font>
<div>&nbsp;</div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">The ep_lock used by echo client causes lockdep to complain.<br>
Multiple locks of the same class are taken concurrently which<br>
appear to lockdep to be prone to deadlocking, and can fill up<br>
lockdep's fixed size stack for locks.<br>
<br>
Ass ep_lock is taken on multiple pages always in ascending page order,<br>
deadlocks don't happen, so this is a false-positive.<br>
<br>
The function of the ep_lock is the same as thats for page_lock(),<br>
which is implemented as a bit-lock using wait_on_bit().&nbsp; lockdep<br>
cannot see these locks, and doesn't really need to.<br>
<br>
So convert ep_lock to a simple bit-lock using wait_on_bit for<br>
waiting.&nbsp; This provides similar functionality, matches how page_lock()<br>
works, and avoids lockdep problems.<br>
<br>
Signed-off-by: NeilBrown &lt;neilb@suse.com&gt;<br>
---<br>
&nbsp;.../staging/lustre/lustre/obdecho/echo_client.c&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; 29 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;-------<br>
&nbsp;1 file changed, 19 insertions(&#43;), 10 deletions(-)<br>
<br>
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c<br>
index 1ddb4a6dd8f3..887df7ce6b5c 100644<br>
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c<br>
&#43;&#43;&#43; b/drivers/staging/lustre/lustre/obdecho/echo_client.c<br>
@@ -78,7 &#43;78,7 @@ struct echo_object_conf {<br>
&nbsp;<br>
&nbsp;struct echo_page {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct cl_page_slice&nbsp;&nbsp; ep_cl;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct mutex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ep_lock;<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ep_lock;<br>
&nbsp;};<br>
&nbsp;<br>
&nbsp;struct echo_lock {<br>
@@ -217,10 &#43;217,13 @@ static int echo_page_own(const struct lu_env *env,<br>
&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct echo_page *ep = cl2echo_page(slice);<br>
&nbsp;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!nonblock)<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_lock(&amp;ep-&gt;ep_lock);<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (!mutex_trylock(&amp;ep-&gt;ep_lock))<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EAGAIN;<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nonblock) {<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (test_and_set_bit(0, &amp;ep-&gt;ep_lock))<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EAGAIN;<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (test_and_set_bit(0, &amp;ep-&gt;ep_lock))<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait_on_bit(&amp;ep-&gt;ep_lock, 0, TASK_UNINTERRUPTIBLE);<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
&nbsp;}<br>
&nbsp;<br>
@@ -230,8 &#43;233,8 @@ static void echo_page_disown(const struct lu_env *env,<br>
&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct echo_page *ep = cl2echo_page(slice);<br>
&nbsp;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LASSERT(mutex_is_locked(&amp;ep-&gt;ep_lock));<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&amp;ep-&gt;ep_lock);<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LASSERT(test_bit(0, &amp;ep-&gt;ep_lock));<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clear_and_wake_up_bit(0, &amp;ep-&gt;ep_lock);<br>
&nbsp;}<br>
&nbsp;<br>
&nbsp;static void echo_page_discard(const struct lu_env *env,<br>
@@ -244,7 &#43;247,7 @@ static void echo_page_discard(const struct lu_env *env,<br>
&nbsp;static int echo_page_is_vmlocked(const struct lu_env *env,<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; const struct cl_page_slice *slice)<br>
&nbsp;{<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mutex_is_locked(&amp;cl2echo_page(slice)-&gt;ep_lock))<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (test_bit(0, &amp;cl2echo_page(slice)-&gt;ep_lock))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -EBUSY;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ENODATA;<br>
&nbsp;}<br>
@@ -279,7 &#43;282,7 @@ static int echo_page_print(const struct lu_env *env,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct echo_page *ep = cl2echo_page(slice);<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*printer)(env, cookie, LUSTRE_ECHO_CLIENT_NAME &quot;-page@%p %d vm@%p\n&quot;,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ep, mutex_is_locked(&amp;ep-&gt;ep_lock),<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ep, test_bit(0, &amp;ep-&gt;ep_lock),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice-&gt;cpl_page-&gt;cp_vmpage);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
&nbsp;}<br>
@@ -339,7 &#43;342,13 @@ static int echo_page_init(const struct lu_env *env, struct cl_object *obj,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct echo_object *eco = cl2echo_obj(obj);<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get_page(page-&gt;cp_vmpage);<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_init(&amp;ep-&gt;ep_lock);<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * ep_lock is similar to the lock_page() lock, and<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * cannot usefully be monitored by lockdep.<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * So just a bit in an &quot;unsigned long&quot; and use the<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * wait_on_bit() interface to wait for the bit to be clera.<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>
&#43;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ep-&gt;ep_lock = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cl_page_slice_add(page, &amp;ep-&gt;ep_cl, obj, index, &amp;echo_page_ops);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; atomic_inc(&amp;eco-&gt;eo_npages);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>
<br>
<br>
_______________________________________________<br>
lustre-devel mailing list<br>
lustre-devel@lists.lustre.org<br>
<a href="http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org">http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org</a><br>
</div>
</span></font></div>
</body>
</html>