mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 04:04:43 +01:00
d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier
Do that before new dentry is visible anywhere. It does create a new possible state for dentries present in ->d_children/->d_sib - DCACHE_PAR_LOOKUP present, negative, unhashed, not in in-lookup hash chains, refcount positive. Those are going to be skipped by all tree-walkers (both d_walk() callbacks in fs/dcache.c and explicit loops over children/sibling lists elsewhere) and dput() is fine with those. NOTE: dropping the final reference to a "normal" in-lookup dentry (in in-lookup hash) is a bug - somebody must've forgotten to call d_lookup_done() on it and bad things will happen. With those it's OK; if/when we get around to making __dentry_kill() complain about such breakage, remember that predicate to check should *not* be just d_in_lookup(victim) but rather a combination of that with !hlist_bl_unhashed(&victim->d_u.d_in_lookup_hash). Might be worth considering later... Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
691fb82ca6
commit
e95db51c81
1 changed files with 7 additions and 3 deletions
10
fs/dcache.c
10
fs/dcache.c
|
|
@ -2546,13 +2546,19 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
|
|||
unsigned int hash = name->hash;
|
||||
struct hlist_bl_head *b = in_lookup_hash(parent, hash);
|
||||
struct hlist_bl_node *node;
|
||||
struct dentry *new = d_alloc(parent, name);
|
||||
struct dentry *new = __d_alloc(parent->d_sb, name);
|
||||
struct dentry *dentry;
|
||||
unsigned seq, r_seq, d_seq;
|
||||
|
||||
if (unlikely(!new))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
new->d_flags |= DCACHE_PAR_LOOKUP;
|
||||
spin_lock(&parent->d_lock);
|
||||
new->d_parent = dget_dlock(parent);
|
||||
hlist_add_head(&new->d_sib, &parent->d_children);
|
||||
spin_unlock(&parent->d_lock);
|
||||
|
||||
retry:
|
||||
rcu_read_lock();
|
||||
seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
|
||||
|
|
@ -2636,8 +2642,6 @@ retry:
|
|||
return dentry;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
/* we can't take ->d_lock here; it's OK, though. */
|
||||
new->d_flags |= DCACHE_PAR_LOOKUP;
|
||||
new->d_wait = wq;
|
||||
hlist_bl_add_head(&new->d_u.d_in_lookup_hash, b);
|
||||
hlist_bl_unlock(b);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue