<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/git/stable/linux.git/fs/dcache.c, branch linux-3.15.y</title>
<subtitle>Linux kernel stable tree</subtitle>
<id>https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=linux-3.15.y</id>
<link rel='self' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=linux-3.15.y'/>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/'/>
<updated>2014-06-16T20:44:09+00:00</updated>
<entry>
<title>lock_parent: don't step on stale -&gt;d_parent of all-but-freed one</title>
<updated>2014-06-16T20:44:09+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-06-12T04:29:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4e358517b2810788777196f038f5a0b3b9936a6a'/>
<id>urn:sha1:4e358517b2810788777196f038f5a0b3b9936a6a</id>
<content type='text'>
commit c2338f2dc7c1e9f6202f370c64ffd7f44f3d4b51 upstream.

Dentry that had been through (or into) __dentry_kill() might be seen
by shrink_dentry_list(); that's normal, it'll be taken off the shrink
list and freed if __dentry_kill() has already finished.  The problem
is, its -&gt;d_parent might be pointing to already freed dentry, so
lock_parent() needs to be careful.

We need to check that dentry hasn't already gone into __dentry_kill()
*and* grab rcu_read_lock() before dropping -&gt;d_lock - the latter makes
sure that whatever we see in -&gt;d_parent after dropping -&gt;d_lock it
won't be freed until we drop rcu_read_lock().

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>dcache: add missing lockdep annotation</title>
<updated>2014-05-31T16:13:21+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2014-05-31T16:13:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9f12600fe425bc28f0ccba034a77783c09c15af4'/>
<id>urn:sha1:9f12600fe425bc28f0ccba034a77783c09c15af4</id>
<content type='text'>
lock_parent() very much on purpose does nested locking of dentries, and
is careful to maintain the right order (lock parent first).  But because
it didn't annotate the nested locking order, lockdep thought it might be
a deadlock on d_lock, and complained.

Add the proper annotation for the inner locking of the child dentry to
make lockdep happy.

Introduced by commit 046b961b45f9 ("shrink_dentry_list(): take parent's
-&gt;d_lock earlier").

Reported-and-tested-by: Josh Boyer &lt;jwboyer@fedoraproject.org&gt;
Cc: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</content>
</entry>
<entry>
<title>dentry_kill() doesn't need the second argument now</title>
<updated>2014-05-30T15:10:33+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-29T13:18:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8cbf74da435d1bd13dbb790f94c7ff67b2fb6af4'/>
<id>urn:sha1:8cbf74da435d1bd13dbb790f94c7ff67b2fb6af4</id>
<content type='text'>
it's 1 in the only remaining caller.

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>dealing with the rest of shrink_dentry_list() livelock</title>
<updated>2014-05-30T15:10:33+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-29T13:11:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b2b80195d8829921506880f6dccd21cabd163d0d'/>
<id>urn:sha1:b2b80195d8829921506880f6dccd21cabd163d0d</id>
<content type='text'>
We have the same problem with -&gt;d_lock order in the inner loop, where
we are dropping references to ancestors.  Same solution, basically -
instead of using dentry_kill() we use lock_parent() (introduced in the
previous commit) to get that lock in a safe way, recheck -&gt;d_count
(in case if lock_parent() has ended up dropping and retaking -&gt;d_lock
and somebody managed to grab a reference during that window), trylock
the inode-&gt;i_lock and use __dentry_kill() to do the rest.

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>shrink_dentry_list(): take parent's -&gt;d_lock earlier</title>
<updated>2014-05-30T15:03:21+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-29T12:54:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=046b961b45f93a92e4c70525a12f3d378bced130'/>
<id>urn:sha1:046b961b45f93a92e4c70525a12f3d378bced130</id>
<content type='text'>
The cause of livelocks there is that we are taking -&gt;d_lock on
dentry and its parent in the wrong order, forcing us to use
trylock on the parent's one.  d_walk() takes them in the right
order, and unfortunately it's not hard to create a situation
when shrink_dentry_list() can't make progress since trylock
keeps failing, and shrink_dcache_parent() or check_submounts_and_drop()
keeps calling d_walk() disrupting the very shrink_dentry_list() it's
waiting for.

Solution is straightforward - if that trylock fails, let's unlock
the dentry itself and take locks in the right order.  We need to
stabilize -&gt;d_parent without holding -&gt;d_lock, but that's doable
using RCU.  And we'd better do that in the very beginning of the
loop in shrink_dentry_list(), since the checks on refcount, etc.
would need to be redone anyway.

That deals with a half of the problem - killing dentries on the
shrink list itself.  Another one (dropping their parents) is
in the next commit.

locking parent is interesting - it would be easy to do rcu_read_lock(),
lock whatever we think is a parent, lock dentry itself and check
if the parent is still the right one.  Except that we need to check
that *before* locking the dentry, or we are risking taking -&gt;d_lock
out of order.  Fortunately, once the D1 is locked, we can check if
D2-&gt;d_parent is equal to D1 without the need to lock D2; D2-&gt;d_parent
can start or stop pointing to D1 only under D1-&gt;d_lock, so taking
D1-&gt;d_lock is enough.  In other words, the right solution is
rcu_read_lock/lock what looks like parent right now/check if it's
still our parent/rcu_read_unlock/lock the child.

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>expand dentry_kill(dentry, 0) in shrink_dentry_list()</title>
<updated>2014-05-29T12:50:08+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-28T17:59:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ff2fde9929feb2aef45377ce56b8b12df85dda69'/>
<id>urn:sha1:ff2fde9929feb2aef45377ce56b8b12df85dda69</id>
<content type='text'>
Result will be massaged to saner shape in the next commits.  It is
ugly, no questions - the point of that one is to be a provably
equivalent transformation (and it might be worth splitting a bit
more).

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>split dentry_kill()</title>
<updated>2014-05-29T12:46:08+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-28T17:51:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e55fd011549eae01a230e3cace6f4d031b6a3453'/>
<id>urn:sha1:e55fd011549eae01a230e3cace6f4d031b6a3453</id>
<content type='text'>
... into trylocks and everything else.  The latter (actual killing)
is __dentry_kill().

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>lift the "already marked killed" case into shrink_dentry_list()</title>
<updated>2014-05-28T13:48:44+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-28T13:48:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=64fd72e0a44bdd62c5ca277cb24d0d02b2d8e9dc'/>
<id>urn:sha1:64fd72e0a44bdd62c5ca277cb24d0d02b2d8e9dc</id>
<content type='text'>
It can happen only when dentry_kill() is called with unlock_on_failure
equal to 0 - other callers had dentry pinned until the moment they've
got -&gt;d_lock and DCACHE_DENTRY_KILLED is set only after lockref_mark_dead().

IOW, only one of three call sites of dentry_kill() might end up reaching
that code.  Just move it there.

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>dcache: don't need rcu in shrink_dentry_list()</title>
<updated>2014-05-03T20:46:16+00:00</updated>
<author>
<name>Miklos Szeredi</name>
<email>mszeredi@suse.cz</email>
</author>
<published>2014-05-02T19:38:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=60942f2f235ce7b817166cdf355eed729094834d'/>
<id>urn:sha1:60942f2f235ce7b817166cdf355eed729094834d</id>
<content type='text'>
Since now the shrink list is private and nobody can free the dentry while
it is on the shrink list, we can remove RCU protection from this.

Signed-off-by: Miklos Szeredi &lt;mszeredi@suse.cz&gt;
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
<entry>
<title>more graceful recovery in umount_collect()</title>
<updated>2014-05-03T20:46:13+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2014-05-03T00:36:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9c8c10e262e0f62cb2530f1b076de979123183dd'/>
<id>urn:sha1:9c8c10e262e0f62cb2530f1b076de979123183dd</id>
<content type='text'>
Start with shrink_dcache_parent(), then scan what remains.

First of all, BUG() is very much an overkill here; we are holding
-&gt;s_umount, and hitting BUG() means that a lot of interesting stuff
will be hanging after that point (sync(2), for example).  Moreover,
in cases when there had been more than one leak, we'll be better
off reporting all of them.  And more than just the last component
of pathname - %pd is there for just such uses...

That was the last user of dentry_lru_del(), so kill it off...

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
</entry>
</feed>
