--- x/fs/namei.c +++ y/fs/namei.c @@ -5529,11 +5529,12 @@ int filename_unlinkat(int dfd, struct fi struct dentry *dentry; struct path path; struct qstr last; - int type; + int type, loop; struct inode *inode; struct delegated_inode delegated_inode = { }; unsigned int lookup_flags = 0; retry: + loop = 0; error = filename_parentat(dfd, name, lookup_flags, &path, &last, &type); if (error) return error; @@ -5545,7 +5546,6 @@ retry: error = mnt_want_write(path.mnt); if (error) goto exit_path_put; -retry_deleg: dentry = start_dirop(path.dentry, &last, lookup_flags); error = PTR_ERR(dentry); if (IS_ERR(dentry)) @@ -5561,7 +5561,6 @@ retry_deleg: goto exit_drop_write; } inode = dentry->d_inode; - ihold(inode); error = security_path_unlink(&path, dentry); if (error) goto exit_end_dirop; @@ -5569,16 +5568,17 @@ retry_deleg: dentry, &delegated_inode); exit_end_dirop: end_dirop(dentry); - iput(inode); /* truncate the inode here */ if (is_delegated(&delegated_inode)) { error = break_deleg_wait(&delegated_inode); if (!error) - goto retry_deleg; + loop = 1; } exit_drop_write: mnt_drop_write(path.mnt); exit_path_put: path_put(&path); + if (loop) + goto retry; if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry;