From: Al Viro <viro@ZenIV.linux.org.uk>
To: John Ogness <john.ogness@linutronix.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>,
Christoph Hellwig <hch@lst.de>,
Thomas Gleixner <tglx@linutronix.de>,
Peter Zijlstra <peterz@infradead.org>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Eric Biederman <ebiederm@xmission.com>
Subject: Re: dcache: remove trylock loops (was Re: [BUG] lock_parent() breakage when used from shrink_dentry_list())
Date: Tue, 13 Mar 2018 23:59:30 +0000 [thread overview]
Message-ID: <20180313235930.GX30522@ZenIV.linux.org.uk> (raw)
In-Reply-To: <87lgevn0ss.fsf@linutronix.de>
On Tue, Mar 13, 2018 at 10:05:55PM +0100, John Ogness wrote:
> > + rcu_read_lock(); /* to protect parent */
> > + spin_unlock(&dentry->d_lock);
> > + parent = READ_ONCE(dentry->d_parent);
>
> The preceeding line should be removed. We already have a "parent" from
> before we did the most recent trylock().
Nope. We have parent, yes, but it had been fetched outside of rcu_read_lock().
So the object it used to point to might have been already freed and we
can't do this:
> > + spin_lock(&parent->d_lock);
To get rid of that reread we'd need to do this:
rcu_read_lock();
parent = dentry->d_parent;
if (IS_ROOT(dentry) || likely(spin_trylock(&parent->d_lock))) {
rcu_read_unlock();
return true;
}
spin_unlock(&dentry->d_lock);
spin_lock(&parent->d_lock);
if (unlikely(parent != dentry->d_parent)) {
....
Come to think of that, it might make sense to lift rcu_read_lock() all the
way out of that sucker. Objections? Below is the incremental I'd fold into
that commit:
diff --git a/fs/dcache.c b/fs/dcache.c
index f0e73c93182b..0d1dac750c0a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1000,7 +1000,6 @@ static bool shrink_lock_dentry(struct dentry *dentry)
inode = dentry->d_inode;
if (inode && unlikely(!spin_trylock(&inode->i_lock))) {
- rcu_read_lock(); /* to protect inode */
spin_unlock(&dentry->d_lock);
spin_lock(&inode->i_lock);
spin_lock(&dentry->d_lock);
@@ -1009,16 +1008,14 @@ static bool shrink_lock_dentry(struct dentry *dentry)
/* changed inode means that somebody had grabbed it */
if (unlikely(inode != dentry->d_inode))
goto out;
- rcu_read_unlock();
}
parent = dentry->d_parent;
+ /* parent will stay allocated until we drop rcu_read_lock */
if (IS_ROOT(dentry) || likely(spin_trylock(&parent->d_lock)))
return true;
- rcu_read_lock(); /* to protect parent */
spin_unlock(&dentry->d_lock);
- parent = READ_ONCE(dentry->d_parent);
spin_lock(&parent->d_lock);
if (unlikely(parent != dentry->d_parent)) {
spin_unlock(&parent->d_lock);
@@ -1026,14 +1023,11 @@ static bool shrink_lock_dentry(struct dentry *dentry)
goto out;
}
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
- if (likely(!dentry->d_lockref.count)) {
- rcu_read_unlock();
+ if (likely(!dentry->d_lockref.count))
return true;
- }
spin_unlock(&parent->d_lock);
out:
spin_unlock(&inode->i_lock);
- rcu_read_unlock();
return false;
}
@@ -1044,8 +1038,10 @@ static void shrink_dentry_list(struct list_head *list)
dentry = list_entry(list->prev, struct dentry, d_lru);
spin_lock(&dentry->d_lock);
+ rcu_read_lock();
if (!shrink_lock_dentry(dentry)) {
bool can_free = false;
+ rcu_read_unlock();
d_shrink_del(dentry);
if (dentry->d_lockref.count < 0)
can_free = dentry->d_flags & DCACHE_MAY_FREE;
@@ -1054,6 +1050,7 @@ static void shrink_dentry_list(struct list_head *list)
dentry_free(dentry);
continue;
}
+ rcu_read_unlock();
d_shrink_del(dentry);
parent = dentry->d_parent;
__dentry_kill(dentry);
next prev parent reply other threads:[~2018-03-13 23:59 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-22 23:50 [PATCH v2 0/6] fs/dcache: avoid trylock loops John Ogness
2018-02-22 23:50 ` [PATCH v2 1/6] fs/dcache: Remove stale comment from dentry_kill() John Ogness
2018-02-22 23:50 ` [PATCH v2 2/6] fs/dcache: Move dentry_kill() below lock_parent() John Ogness
2018-02-22 23:50 ` [PATCH v2 3/6] fs/dcache: Avoid the try_lock loop in d_delete() John Ogness
2018-02-23 2:08 ` Al Viro
2018-02-22 23:50 ` [PATCH v2 4/6] fs/dcache: Avoid the try_lock loops in dentry_kill() John Ogness
2018-02-23 2:22 ` Al Viro
2018-02-23 3:12 ` Al Viro
2018-02-23 3:16 ` Al Viro
2018-02-23 5:46 ` Al Viro
2018-02-22 23:50 ` [PATCH v2 5/6] fs/dcache: Avoid a try_lock loop in shrink_dentry_list() John Ogness
2018-02-23 3:48 ` Al Viro
2018-02-22 23:50 ` [PATCH v2 6/6] fs/dcache: Avoid remaining " John Ogness
2018-02-23 3:58 ` Al Viro
2018-02-23 4:08 ` Al Viro
2018-02-23 13:57 ` John Ogness
2018-02-23 15:09 ` Al Viro
2018-02-23 17:42 ` Al Viro
2018-02-23 20:13 ` [BUG] lock_parent() breakage when used from shrink_dentry_list() (was Re: [PATCH v2 6/6] fs/dcache: Avoid remaining try_lock loop in shrink_dentry_list()) Al Viro
2018-02-23 21:35 ` Linus Torvalds
2018-02-24 0:22 ` Al Viro
2018-02-25 7:40 ` Al Viro
2018-02-27 5:16 ` dcache: remove trylock loops (was Re: [BUG] lock_parent() breakage when used from shrink_dentry_list()) John Ogness
2018-03-12 19:13 ` Al Viro
2018-03-12 20:05 ` Al Viro
2018-03-12 20:33 ` Al Viro
2018-03-13 1:12 ` NeilBrown
2018-04-28 0:10 ` Al Viro
2018-03-12 20:23 ` Eric W. Biederman
2018-03-12 20:39 ` Al Viro
2018-03-12 23:28 ` Eric W. Biederman
2018-03-12 23:52 ` Eric W. Biederman
2018-03-13 0:37 ` Al Viro
2018-03-13 0:50 ` Al Viro
2018-03-13 4:02 ` Eric W. Biederman
2018-03-14 23:20 ` [PATCH] fs: Teach path_connected to handle nfs filesystems with multiple roots Eric W. Biederman
2018-03-15 22:34 ` Al Viro
2018-03-13 0:36 ` dcache: remove trylock loops (was Re: [BUG] lock_parent() breakage when used from shrink_dentry_list()) Al Viro
2018-03-12 22:14 ` Thomas Gleixner
2018-03-13 20:46 ` John Ogness
2018-03-13 21:05 ` John Ogness
2018-03-13 23:59 ` Al Viro [this message]
2018-03-14 2:58 ` Matthew Wilcox
2018-03-14 8:18 ` John Ogness
2018-03-02 9:04 ` [BUG] lock_parent() breakage when used from shrink_dentry_list() (was Re: [PATCH v2 6/6] fs/dcache: Avoid remaining try_lock loop in shrink_dentry_list()) Sebastian Andrzej Siewior
2018-02-23 0:59 ` [PATCH v2 0/6] fs/dcache: avoid trylock loops Linus Torvalds
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180313235930.GX30522@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=bigeasy@linutronix.de \
--cc=ebiederm@xmission.com \
--cc=hch@lst.de \
--cc=john.ogness@linutronix.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).