diff options
| -rw-r--r-- | fs/exportfs/expfs.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 87e6dca69e43..c65b748688ff 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
| @@ -90,6 +90,24 @@ find_disconnected_root(struct dentry *dentry) | |||
| 90 | return dentry; | 90 | return dentry; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static void clear_disconnected(struct dentry *dentry) | ||
| 94 | { | ||
| 95 | dget(dentry); | ||
| 96 | while (dentry->d_flags & DCACHE_DISCONNECTED) { | ||
| 97 | struct dentry *parent = dget_parent(dentry); | ||
| 98 | |||
| 99 | WARN_ON_ONCE(IS_ROOT(dentry)); | ||
| 100 | |||
| 101 | spin_lock(&dentry->d_lock); | ||
| 102 | dentry->d_flags &= ~DCACHE_DISCONNECTED; | ||
| 103 | spin_unlock(&dentry->d_lock); | ||
| 104 | |||
| 105 | dput(dentry); | ||
| 106 | dentry = parent; | ||
| 107 | } | ||
| 108 | dput(dentry); | ||
| 109 | } | ||
| 110 | |||
| 93 | /* | 111 | /* |
| 94 | * Make sure target_dir is fully connected to the dentry tree. | 112 | * Make sure target_dir is fully connected to the dentry tree. |
| 95 | * | 113 | * |
| @@ -128,10 +146,9 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf) | |||
| 128 | 146 | ||
| 129 | if (!IS_ROOT(pd)) { | 147 | if (!IS_ROOT(pd)) { |
| 130 | /* must have found a connected parent - great */ | 148 | /* must have found a connected parent - great */ |
| 131 | spin_lock(&pd->d_lock); | 149 | clear_disconnected(target_dir); |
| 132 | pd->d_flags &= ~DCACHE_DISCONNECTED; | 150 | dput(pd); |
| 133 | spin_unlock(&pd->d_lock); | 151 | break; |
| 134 | noprogress = 0; | ||
| 135 | } else { | 152 | } else { |
| 136 | /* | 153 | /* |
| 137 | * We have hit the top of a disconnected path, try to | 154 | * We have hit the top of a disconnected path, try to |
