|
|
@@ -647,11 +647,16 @@ again:
|
|
|
spin_unlock(&parent->d_lock);
|
|
|
goto again;
|
|
|
}
|
|
|
- rcu_read_unlock();
|
|
|
- if (parent != dentry)
|
|
|
+ if (parent != dentry) {
|
|
|
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
- else
|
|
|
+ if (unlikely(dentry->d_lockref.count < 0)) {
|
|
|
+ spin_unlock(&parent->d_lock);
|
|
|
+ parent = NULL;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
parent = NULL;
|
|
|
+ }
|
|
|
+ rcu_read_unlock();
|
|
|
return parent;
|
|
|
}
|
|
|
|
|
|
@@ -2474,7 +2479,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
|
|
|
|
|
|
retry:
|
|
|
rcu_read_lock();
|
|
|
- seq = smp_load_acquire(&parent->d_inode->i_dir_seq) & ~1;
|
|
|
+ seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
|
|
|
r_seq = read_seqbegin(&rename_lock);
|
|
|
dentry = __d_lookup_rcu(parent, name, &d_seq);
|
|
|
if (unlikely(dentry)) {
|
|
|
@@ -2495,8 +2500,14 @@ retry:
|
|
|
rcu_read_unlock();
|
|
|
goto retry;
|
|
|
}
|
|
|
+
|
|
|
+ if (unlikely(seq & 1)) {
|
|
|
+ rcu_read_unlock();
|
|
|
+ goto retry;
|
|
|
+ }
|
|
|
+
|
|
|
hlist_bl_lock(b);
|
|
|
- if (unlikely(parent->d_inode->i_dir_seq != seq)) {
|
|
|
+ if (unlikely(READ_ONCE(parent->d_inode->i_dir_seq) != seq)) {
|
|
|
hlist_bl_unlock(b);
|
|
|
rcu_read_unlock();
|
|
|
goto retry;
|