92 lines
2.8 KiB
Diff
92 lines
2.8 KiB
Diff
From: Al Viro <viro@zeniv.linux.org.uk>
|
|
Date: Sun, 11 Mar 2018 15:15:46 -0400
|
|
Subject: [PATCH 16/17] fold dentry_lock_for_move() into its sole caller and
|
|
clean it up
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.16/older/patches-4.16.7-rt1.tar.xz
|
|
|
|
Upstream commit 42177007aa277af3e37bf2ae3efdfe795c81d700
|
|
|
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
fs/dcache.c | 49 +++++++++++++++++++++++--------------------------
|
|
1 file changed, 23 insertions(+), 26 deletions(-)
|
|
|
|
--- a/fs/dcache.c
|
|
+++ b/fs/dcache.c
|
|
@@ -2773,25 +2773,6 @@ static void copy_name(struct dentry *den
|
|
kfree_rcu(old_name, u.head);
|
|
}
|
|
|
|
-static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
|
|
-{
|
|
- if (IS_ROOT(dentry) || dentry->d_parent == target->d_parent)
|
|
- spin_lock(&target->d_parent->d_lock);
|
|
- else {
|
|
- if (d_ancestor(dentry->d_parent, target->d_parent)) {
|
|
- spin_lock(&dentry->d_parent->d_lock);
|
|
- spin_lock_nested(&target->d_parent->d_lock,
|
|
- DENTRY_D_LOCK_NESTED);
|
|
- } else {
|
|
- spin_lock(&target->d_parent->d_lock);
|
|
- spin_lock_nested(&dentry->d_parent->d_lock,
|
|
- DENTRY_D_LOCK_NESTED);
|
|
- }
|
|
- }
|
|
- spin_lock_nested(&dentry->d_lock, 2);
|
|
- spin_lock_nested(&target->d_lock, 3);
|
|
-}
|
|
-
|
|
/*
|
|
* __d_move - move a dentry
|
|
* @dentry: entry to move
|
|
@@ -2806,16 +2787,34 @@ static void dentry_lock_for_move(struct
|
|
static void __d_move(struct dentry *dentry, struct dentry *target,
|
|
bool exchange)
|
|
{
|
|
- struct dentry *old_parent;
|
|
+ struct dentry *old_parent, *p;
|
|
struct inode *dir = NULL;
|
|
unsigned n;
|
|
- if (!dentry->d_inode)
|
|
- printk(KERN_WARNING "VFS: moving negative dcache entry\n");
|
|
|
|
- BUG_ON(d_ancestor(dentry, target));
|
|
+ WARN_ON(!dentry->d_inode);
|
|
+ if (WARN_ON(dentry == target))
|
|
+ return;
|
|
+
|
|
BUG_ON(d_ancestor(target, dentry));
|
|
+ old_parent = dentry->d_parent;
|
|
+ p = d_ancestor(old_parent, target);
|
|
+ if (IS_ROOT(dentry)) {
|
|
+ BUG_ON(p);
|
|
+ spin_lock(&target->d_parent->d_lock);
|
|
+ } else if (!p) {
|
|
+ /* target is not a descendent of dentry->d_parent */
|
|
+ spin_lock(&target->d_parent->d_lock);
|
|
+ spin_lock_nested(&old_parent->d_lock, DENTRY_D_LOCK_NESTED);
|
|
+ } else {
|
|
+ BUG_ON(p == dentry);
|
|
+ spin_lock(&old_parent->d_lock);
|
|
+ if (p != target)
|
|
+ spin_lock_nested(&target->d_parent->d_lock,
|
|
+ DENTRY_D_LOCK_NESTED);
|
|
+ }
|
|
+ spin_lock_nested(&dentry->d_lock, 2);
|
|
+ spin_lock_nested(&target->d_lock, 3);
|
|
|
|
- dentry_lock_for_move(dentry, target);
|
|
if (unlikely(d_in_lookup(target))) {
|
|
dir = target->d_parent->d_inode;
|
|
n = start_dir_add(dir);
|
|
@@ -2825,8 +2824,6 @@ static void __d_move(struct dentry *dent
|
|
write_seqcount_begin(&dentry->d_seq);
|
|
write_seqcount_begin_nested(&target->d_seq, DENTRY_D_LOCK_NESTED);
|
|
|
|
- old_parent = dentry->d_parent;
|
|
-
|
|
/* unhash both */
|
|
if (!d_unhashed(dentry))
|
|
___d_drop(dentry);
|