From: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
To: stable <stable@vger.kernel.org>
Cc: Greg-KH <gregkh@linuxfoundation.org>,
Al Viro <viro@zeniv.linux.org.uk>,
Miklos Szeredi <mszeredi@suse.cz>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: [PATCH-v3.14.y 5/8] dentry_kill(): don't try to remove from shrink list
Date: Thu, 13 Aug 2015 21:23:43 +0000 [thread overview]
Message-ID: <1439501026-19955-6-git-send-email-nab@linux-iscsi.org> (raw)
In-Reply-To: <1439501026-19955-1-git-send-email-nab@linux-iscsi.org>
From: Al Viro <viro@zeniv.linux.org.uk>
commit 41edf278fc2f042f4e22a12ed87d19c5201210e1 upstream.
If the victim in on the shrink list, don't remove it from there.
If shrink_dentry_list() manages to remove it from the list before
we are done - fine, we'll just free it as usual. If not - mark
it with new flag (DCACHE_MAY_FREE) and leave it there.
Eventually, shrink_dentry_list() will get to it, remove the sucker
from shrink list and call dentry_kill(dentry, 0). Which is where
we'll deal with freeing.
Since now dentry_kill(dentry, 0) may happen after or during
dentry_kill(dentry, 1), we need to recognize that (by seeing
DCACHE_DENTRY_KILLED already set), unlock everything
and either free the sucker (in case DCACHE_MAY_FREE has been
set) or leave it for ongoing dentry_kill(dentry, 1) to deal with.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/dcache.c | 27 +++++++++++++++++++--------
include/linux/dcache.h | 2 ++
2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 16f9066..099308a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -466,7 +466,14 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure)
__releases(dentry->d_lock)
{
struct inode *inode;
- struct dentry *parent;
+ struct dentry *parent = NULL;
+ bool can_free = true;
+
+ if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) {
+ can_free = dentry->d_flags & DCACHE_MAY_FREE;
+ spin_unlock(&dentry->d_lock);
+ goto out;
+ }
inode = dentry->d_inode;
if (inode && !spin_trylock(&inode->i_lock)) {
@@ -477,9 +484,7 @@ relock:
}
return dentry; /* try again with same dentry */
}
- if (IS_ROOT(dentry))
- parent = NULL;
- else
+ if (!IS_ROOT(dentry))
parent = dentry->d_parent;
if (parent && !spin_trylock(&parent->d_lock)) {
if (inode)
@@ -502,8 +507,6 @@ relock:
if (dentry->d_flags & DCACHE_LRU_LIST) {
if (!(dentry->d_flags & DCACHE_SHRINK_LIST))
d_lru_del(dentry);
- else
- d_shrink_del(dentry);
}
/* if it was on the hash then remove it */
__d_drop(dentry);
@@ -525,7 +528,15 @@ relock:
if (dentry->d_op && dentry->d_op->d_release)
dentry->d_op->d_release(dentry);
- dentry_free(dentry);
+ spin_lock(&dentry->d_lock);
+ if (dentry->d_flags & DCACHE_SHRINK_LIST) {
+ dentry->d_flags |= DCACHE_MAY_FREE;
+ can_free = false;
+ }
+ spin_unlock(&dentry->d_lock);
+out:
+ if (likely(can_free))
+ dentry_free(dentry);
return parent;
}
@@ -830,7 +841,7 @@ static void shrink_dentry_list(struct list_head *list)
* We found an inuse dentry which was not removed from
* the LRU because of laziness during lookup. Do not free it.
*/
- if (dentry->d_lockref.count) {
+ if ((int)dentry->d_lockref.count > 0) {
spin_unlock(&dentry->d_lock);
continue;
}
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 0f0eb1c..2a23ecb 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -221,6 +221,8 @@ struct dentry_operations {
#define DCACHE_SYMLINK_TYPE 0x00300000 /* Symlink */
#define DCACHE_FILE_TYPE 0x00400000 /* Other file type */
+#define DCACHE_MAY_FREE 0x00800000
+
extern seqlock_t rename_lock;
static inline int dname_external(const struct dentry *dentry)
--
1.8.5.3
next prev parent reply other threads:[~2015-08-13 21:23 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-13 21:23 [PATCH-v3.14.y 0/8] Stable backport for dcache shrink list corruption Nicholas A. Bellinger
2015-08-13 21:23 ` [PATCH-v3.14.y 1/8] fold d_kill() and d_free() Nicholas A. Bellinger
2015-08-13 21:23 ` [PATCH-v3.14.y 2/8] fold try_prune_one_dentry() Nicholas A. Bellinger
2015-08-13 21:23 ` [PATCH-v3.14.y 3/8] new helper: dentry_free() Nicholas A. Bellinger
2015-08-13 21:23 ` [PATCH-v3.14.y 4/8] expand the call of dentry_lru_del() in dentry_kill() Nicholas A. Bellinger
2015-08-13 21:23 ` Nicholas A. Bellinger [this message]
2015-08-13 21:23 ` [PATCH-v3.14.y 6/8] don't remove from shrink list in select_collect() Nicholas A. Bellinger
2015-08-13 21:23 ` [PATCH-v3.14.y 7/8] more graceful recovery in umount_collect() Nicholas A. Bellinger
2015-08-13 21:23 ` [PATCH-v3.14.y 8/8] dcache: don't need rcu in shrink_dentry_list() Nicholas A. Bellinger
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=1439501026-19955-6-git-send-email-nab@linux-iscsi.org \
--to=nab@linux-iscsi.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=mszeredi@suse.cz \
--cc=stable@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/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).