Patch "dentry_kill(): don't try to remove from shrink list" has been added to the 3.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
dentry_kill(): don't try to remove from shrink list
to the 3.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
dentry_kill-don-t-try-to-remove-from-shrink-list.patch
and it can be found in the queue-3.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
41edf278fc2f042f4e22a12ed87d19c5201210e1Mon Sep 17 00:00:00 2001
From: Al Viro <[email protected]>
Date: Thu, 1 May 2014 10:30:00 -0400
Subject: dentry_kill(): don't try to remove from shrink list
From: Al Viro <[email protected]>
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.
--- fs/dcache.c | 27 +++++++++++++++++++-------- include/linux/dcache.h | 2 ++ 2 files changed, 21 insertions(+), 8 deletions(-)
fs/dcache.c +19 -8
@@ -466,7 +466,14 @@ dentry_kill(struct dentry *dentry, int u __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 li* 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 ; }
include/linux/dcache.h +2 -0
@@ -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)
Patches currently in stable-queue which might be from [email protected] are
queue-3.14/new-helper-dentry_free.patch queue-3.14/don-t-remove-from-shrink-list-in-select_collect.patch queue-3.14/fold-try_prune_one_dentry.patch queue-3.14/more-graceful-recovery-in-umount_collect.patch queue-3.14/expand-the-call-of-dentry_lru_del-in-dentry_kill.patch queue-3.14/dcache-don-t-need-rcu-in-shrink_dentry_list.patch queue-3.14/path_openat-fix-double-fput.patchqueue-3.14/fold-d_kill-and-d_free.patch queue-3.14/ipc-modify-message-queue-accounting-to-not-take-kernel-data-structures-into-account.patch queue-3.14/dentry_kill-don-t-try-to-remove-from-shrink-list.patch queue-3.14/sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch