On Wed, Sep 21, 2022 at 07:43:37AM +0900, Namjae Jeon wrote: FWIW, it probably needs a few comments: // c1 and p2 should be on the same fs > +struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2) > +{ > + if (READ_ONCE(c1->d_parent) == p2) { // hopefully won't need to touch ->s_vfs_rename_mutex at all. > + inode_lock_nested(p2->d_inode, I_MUTEX_PARENT); // now that p2 is locked, nobody can move in or out of it, // so the test below is safe > + if (likely(c1->d_parent == p2)) > + return NULL; > + // c1 got moved out of p2 while we'd been taking locks; // unlock and fall back to slow case > + inode_unlock(p2->d_inode); > + } > + > + mutex_lock(&c1->d_sb->s_vfs_rename_mutex); // nobody can move out of any directories on this fs > + if (likely(c1->d_parent != p2)) > + return lock_two_directories(c1->d_parent, p2); > + // c1 got moved into p2 while we were taking locks; // we need p2 locked and ->s_vfs_rename_mutex unlocked, // for consistency with lock_rename(). > + inode_lock_nested(p2->d_inode, I_MUTEX_PARENT); > + mutex_unlock(&c1->d_sb->s_vfs_rename_mutex); > + return NULL; > +} > +EXPORT_SYMBOL(lock_rename_child);