From: Xiubo Li <xiubli@xxxxxxxxxx> When unlinking a file the kclient will send a unlink request to MDS by holding the dentry reference, and then the MDS will return 2 replies, which are unsafe reply and a deferred safe reply. After the unsafe reply received the kernel will return and succeed the unlink request to user space apps. Only when the safe reply received the dentry's reference will be released. Or the dentry will only be unhashed from dcache. But when the open_by_handle_at() begins to open the unlinked files it will succeed. URL: https://tracker.ceph.com/issues/56524 Signed-off-by: Xiubo Li <xiubli@xxxxxxxxxx> --- V2: - If the dentry was released and inode is evicted such as by dropping the caches, it will allocate a new dentry, which is also unhashed. fs/ceph/export.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 0ebf2bd93055..5edc1d31cd79 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -182,6 +182,7 @@ struct inode *ceph_lookup_inode(struct super_block *sb, u64 ino) static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino) { struct inode *inode = __lookup_inode(sb, ino); + struct dentry *dentry; int err; if (IS_ERR(inode)) @@ -197,7 +198,21 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino) iput(inode); return ERR_PTR(-ESTALE); } - return d_obtain_alias(inode); + + /* + * -ESTALE if the dentry exists and is unhashed, + * which should be being released + */ + dentry = d_find_any_alias(inode); + if (dentry && unlikely(d_unhashed(dentry))) { + dput(dentry); + return ERR_PTR(-ESTALE); + } + + if (!dentry) + dentry = d_obtain_alias(inode); + + return dentry; } static struct dentry *__snapfh_to_dentry(struct super_block *sb, -- 2.36.0.rc1