Loading fs/dcache.c +34 −17 Original line number Diff line number Diff line Loading @@ -2213,14 +2213,15 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry, * The hash value has to match the hash queue that the dentry is on.. */ /* * d_move - move a dentry * __d_move - move a dentry * @dentry: entry to move * @target: new dentry * * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. * dcache entries should not be moved in this way. Caller hold * rename_lock. */ void d_move(struct dentry * dentry, struct dentry * target) static void __d_move(struct dentry * dentry, struct dentry * target) { if (!dentry->d_inode) printk(KERN_WARNING "VFS: moving negative dcache entry\n"); Loading @@ -2228,8 +2229,6 @@ void d_move(struct dentry * dentry, struct dentry * target) BUG_ON(d_ancestor(dentry, target)); BUG_ON(d_ancestor(target, dentry)); write_seqlock(&rename_lock); dentry_lock_for_move(dentry, target); write_seqcount_begin(&dentry->d_seq); Loading Loading @@ -2275,6 +2274,20 @@ void d_move(struct dentry * dentry, struct dentry * target) spin_unlock(&target->d_lock); fsnotify_d_move(dentry); spin_unlock(&dentry->d_lock); } /* * d_move - move a dentry * @dentry: entry to move * @target: new dentry * * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. */ void d_move(struct dentry *dentry, struct dentry *target) { write_seqlock(&rename_lock); __d_move(dentry, target); write_sequnlock(&rename_lock); } EXPORT_SYMBOL(d_move); Loading Loading @@ -2302,7 +2315,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2) * This helper attempts to cope with remotely renamed directories * * It assumes that the caller is already holding * dentry->d_parent->d_inode->i_mutex and the inode->i_lock * dentry->d_parent->d_inode->i_mutex, inode->i_lock and rename_lock * * Note: If ever the locking in lock_rename() changes, then please * remember to update this too... Loading @@ -2317,11 +2330,6 @@ static struct dentry *__d_unalias(struct inode *inode, if (alias->d_parent == dentry->d_parent) goto out_unalias; /* Check for loops */ ret = ERR_PTR(-ELOOP); if (d_ancestor(alias, dentry)) goto out_err; /* See lock_rename() */ ret = ERR_PTR(-EBUSY); if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) Loading @@ -2331,7 +2339,7 @@ static struct dentry *__d_unalias(struct inode *inode, goto out_err; m2 = &alias->d_parent->d_inode->i_mutex; out_unalias: d_move(alias, dentry); __d_move(alias, dentry); ret = alias; out_err: spin_unlock(&inode->i_lock); Loading Loading @@ -2416,15 +2424,24 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) alias = __d_find_alias(inode, 0); if (alias) { actual = alias; /* Is this an anonymous mountpoint that we could splice * into our tree? */ if (IS_ROOT(alias)) { write_seqlock(&rename_lock); if (d_ancestor(alias, dentry)) { /* Check for loops */ actual = ERR_PTR(-ELOOP); } else if (IS_ROOT(alias)) { /* Is this an anonymous mountpoint that we * could splice into our tree? */ __d_materialise_dentry(dentry, alias); write_sequnlock(&rename_lock); __d_drop(alias); goto found; } /* Nope, but we must(!) avoid directory aliasing */ } else { /* Nope, but we must(!) avoid directory * aliasing */ actual = __d_unalias(inode, dentry, alias); } write_sequnlock(&rename_lock); if (IS_ERR(actual)) dput(alias); goto out_nolock; Loading fs/namei.c +2 −0 Original line number Diff line number Diff line Loading @@ -433,6 +433,8 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) goto err_parent; BUG_ON(nd->inode != parent->d_inode); } else { if (dentry->d_parent != parent) goto err_parent; spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); if (!__d_rcu_to_refcount(dentry, nd->seq)) goto err_child; Loading Loading
fs/dcache.c +34 −17 Original line number Diff line number Diff line Loading @@ -2213,14 +2213,15 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry, * The hash value has to match the hash queue that the dentry is on.. */ /* * d_move - move a dentry * __d_move - move a dentry * @dentry: entry to move * @target: new dentry * * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. * dcache entries should not be moved in this way. Caller hold * rename_lock. */ void d_move(struct dentry * dentry, struct dentry * target) static void __d_move(struct dentry * dentry, struct dentry * target) { if (!dentry->d_inode) printk(KERN_WARNING "VFS: moving negative dcache entry\n"); Loading @@ -2228,8 +2229,6 @@ void d_move(struct dentry * dentry, struct dentry * target) BUG_ON(d_ancestor(dentry, target)); BUG_ON(d_ancestor(target, dentry)); write_seqlock(&rename_lock); dentry_lock_for_move(dentry, target); write_seqcount_begin(&dentry->d_seq); Loading Loading @@ -2275,6 +2274,20 @@ void d_move(struct dentry * dentry, struct dentry * target) spin_unlock(&target->d_lock); fsnotify_d_move(dentry); spin_unlock(&dentry->d_lock); } /* * d_move - move a dentry * @dentry: entry to move * @target: new dentry * * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. */ void d_move(struct dentry *dentry, struct dentry *target) { write_seqlock(&rename_lock); __d_move(dentry, target); write_sequnlock(&rename_lock); } EXPORT_SYMBOL(d_move); Loading Loading @@ -2302,7 +2315,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2) * This helper attempts to cope with remotely renamed directories * * It assumes that the caller is already holding * dentry->d_parent->d_inode->i_mutex and the inode->i_lock * dentry->d_parent->d_inode->i_mutex, inode->i_lock and rename_lock * * Note: If ever the locking in lock_rename() changes, then please * remember to update this too... Loading @@ -2317,11 +2330,6 @@ static struct dentry *__d_unalias(struct inode *inode, if (alias->d_parent == dentry->d_parent) goto out_unalias; /* Check for loops */ ret = ERR_PTR(-ELOOP); if (d_ancestor(alias, dentry)) goto out_err; /* See lock_rename() */ ret = ERR_PTR(-EBUSY); if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) Loading @@ -2331,7 +2339,7 @@ static struct dentry *__d_unalias(struct inode *inode, goto out_err; m2 = &alias->d_parent->d_inode->i_mutex; out_unalias: d_move(alias, dentry); __d_move(alias, dentry); ret = alias; out_err: spin_unlock(&inode->i_lock); Loading Loading @@ -2416,15 +2424,24 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) alias = __d_find_alias(inode, 0); if (alias) { actual = alias; /* Is this an anonymous mountpoint that we could splice * into our tree? */ if (IS_ROOT(alias)) { write_seqlock(&rename_lock); if (d_ancestor(alias, dentry)) { /* Check for loops */ actual = ERR_PTR(-ELOOP); } else if (IS_ROOT(alias)) { /* Is this an anonymous mountpoint that we * could splice into our tree? */ __d_materialise_dentry(dentry, alias); write_sequnlock(&rename_lock); __d_drop(alias); goto found; } /* Nope, but we must(!) avoid directory aliasing */ } else { /* Nope, but we must(!) avoid directory * aliasing */ actual = __d_unalias(inode, dentry, alias); } write_sequnlock(&rename_lock); if (IS_ERR(actual)) dput(alias); goto out_nolock; Loading
fs/namei.c +2 −0 Original line number Diff line number Diff line Loading @@ -433,6 +433,8 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) goto err_parent; BUG_ON(nd->inode != parent->d_inode); } else { if (dentry->d_parent != parent) goto err_parent; spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); if (!__d_rcu_to_refcount(dentry, nd->seq)) goto err_child; Loading