aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 37f72ee5bf7..fbdcbca4072 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1813,8 +1813,6 @@ seqretry:
1813 tname = dentry->d_name.name; 1813 tname = dentry->d_name.name;
1814 i = dentry->d_inode; 1814 i = dentry->d_inode;
1815 prefetch(tname); 1815 prefetch(tname);
1816 if (i)
1817 prefetch(i);
1818 /* 1816 /*
1819 * This seqcount check is required to ensure name and 1817 * This seqcount check is required to ensure name and
1820 * len are loaded atomically, so as not to walk off the 1818 * len are loaded atomically, so as not to walk off the
@@ -2213,14 +2211,15 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry,
2213 * The hash value has to match the hash queue that the dentry is on.. 2211 * The hash value has to match the hash queue that the dentry is on..
2214 */ 2212 */
2215/* 2213/*
2216 * d_move - move a dentry 2214 * __d_move - move a dentry
2217 * @dentry: entry to move 2215 * @dentry: entry to move
2218 * @target: new dentry 2216 * @target: new dentry
2219 * 2217 *
2220 * Update the dcache to reflect the move of a file name. Negative 2218 * Update the dcache to reflect the move of a file name. Negative
2221 * dcache entries should not be moved in this way. 2219 * dcache entries should not be moved in this way. Caller hold
2220 * rename_lock.
2222 */ 2221 */
2223void d_move(struct dentry * dentry, struct dentry * target) 2222static void __d_move(struct dentry * dentry, struct dentry * target)
2224{ 2223{
2225 if (!dentry->d_inode) 2224 if (!dentry->d_inode)
2226 printk(KERN_WARNING "VFS: moving negative dcache entry\n"); 2225 printk(KERN_WARNING "VFS: moving negative dcache entry\n");
@@ -2228,8 +2227,6 @@ void d_move(struct dentry * dentry, struct dentry * target)
2228 BUG_ON(d_ancestor(dentry, target)); 2227 BUG_ON(d_ancestor(dentry, target));
2229 BUG_ON(d_ancestor(target, dentry)); 2228 BUG_ON(d_ancestor(target, dentry));
2230 2229
2231 write_seqlock(&rename_lock);
2232
2233 dentry_lock_for_move(dentry, target); 2230 dentry_lock_for_move(dentry, target);
2234 2231
2235 write_seqcount_begin(&dentry->d_seq); 2232 write_seqcount_begin(&dentry->d_seq);
@@ -2275,6 +2272,20 @@ void d_move(struct dentry * dentry, struct dentry * target)
2275 spin_unlock(&target->d_lock); 2272 spin_unlock(&target->d_lock);
2276 fsnotify_d_move(dentry); 2273 fsnotify_d_move(dentry);
2277 spin_unlock(&dentry->d_lock); 2274 spin_unlock(&dentry->d_lock);
2275}
2276
2277/*
2278 * d_move - move a dentry
2279 * @dentry: entry to move
2280 * @target: new dentry
2281 *
2282 * Update the dcache to reflect the move of a file name. Negative
2283 * dcache entries should not be moved in this way.
2284 */
2285void d_move(struct dentry *dentry, struct dentry *target)
2286{
2287 write_seqlock(&rename_lock);
2288 __d_move(dentry, target);
2278 write_sequnlock(&rename_lock); 2289 write_sequnlock(&rename_lock);
2279} 2290}
2280EXPORT_SYMBOL(d_move); 2291EXPORT_SYMBOL(d_move);
@@ -2302,7 +2313,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
2302 * This helper attempts to cope with remotely renamed directories 2313 * This helper attempts to cope with remotely renamed directories
2303 * 2314 *
2304 * It assumes that the caller is already holding 2315 * It assumes that the caller is already holding
2305 * dentry->d_parent->d_inode->i_mutex and the inode->i_lock 2316 * dentry->d_parent->d_inode->i_mutex, inode->i_lock and rename_lock
2306 * 2317 *
2307 * Note: If ever the locking in lock_rename() changes, then please 2318 * Note: If ever the locking in lock_rename() changes, then please
2308 * remember to update this too... 2319 * remember to update this too...
@@ -2317,11 +2328,6 @@ static struct dentry *__d_unalias(struct inode *inode,
2317 if (alias->d_parent == dentry->d_parent) 2328 if (alias->d_parent == dentry->d_parent)
2318 goto out_unalias; 2329 goto out_unalias;
2319 2330
2320 /* Check for loops */
2321 ret = ERR_PTR(-ELOOP);
2322 if (d_ancestor(alias, dentry))
2323 goto out_err;
2324
2325 /* See lock_rename() */ 2331 /* See lock_rename() */
2326 ret = ERR_PTR(-EBUSY); 2332 ret = ERR_PTR(-EBUSY);
2327 if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) 2333 if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
@@ -2331,7 +2337,7 @@ static struct dentry *__d_unalias(struct inode *inode,
2331 goto out_err; 2337 goto out_err;
2332 m2 = &alias->d_parent->d_inode->i_mutex; 2338 m2 = &alias->d_parent->d_inode->i_mutex;
2333out_unalias: 2339out_unalias:
2334 d_move(alias, dentry); 2340 __d_move(alias, dentry);
2335 ret = alias; 2341 ret = alias;
2336out_err: 2342out_err:
2337 spin_unlock(&inode->i_lock); 2343 spin_unlock(&inode->i_lock);
@@ -2416,15 +2422,24 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
2416 alias = __d_find_alias(inode, 0); 2422 alias = __d_find_alias(inode, 0);
2417 if (alias) { 2423 if (alias) {
2418 actual = alias; 2424 actual = alias;
2419 /* Is this an anonymous mountpoint that we could splice 2425 write_seqlock(&rename_lock);
2420 * into our tree? */ 2426
2421 if (IS_ROOT(alias)) { 2427 if (d_ancestor(alias, dentry)) {
2428 /* Check for loops */
2429 actual = ERR_PTR(-ELOOP);
2430 } else if (IS_ROOT(alias)) {
2431 /* Is this an anonymous mountpoint that we
2432 * could splice into our tree? */
2422 __d_materialise_dentry(dentry, alias); 2433 __d_materialise_dentry(dentry, alias);
2434 write_sequnlock(&rename_lock);
2423 __d_drop(alias); 2435 __d_drop(alias);
2424 goto found; 2436 goto found;
2437 } else {
2438 /* Nope, but we must(!) avoid directory
2439 * aliasing */
2440 actual = __d_unalias(inode, dentry, alias);
2425 } 2441 }
2426 /* Nope, but we must(!) avoid directory aliasing */ 2442 write_sequnlock(&rename_lock);
2427 actual = __d_unalias(inode, dentry, alias);
2428 if (IS_ERR(actual)) 2443 if (IS_ERR(actual))
2429 dput(alias); 2444 dput(alias);
2430 goto out_nolock; 2445 goto out_nolock;