Skip to contentSkip to conversation

Patch "dentry_kill(): don't try to remove from shrink list" has been added to the 3.14-stable tree

PATCH [email protected] 1 participant 1 message Aug 14, 2015

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

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 41edf278fc2f042f4e22a12ed87d19c5201210e1 Mon 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.

Cc "Nicholas A. Bellinger" <[email protected]>
---
 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.patch
queue-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