Commit 8c7c3d5b authored by Yan, Zheng's avatar Yan, Zheng Committed by Greg Kroah-Hartman

ceph: drop negative child dentries before try pruning inode's alias

commit 040d7860 upstream.

Negative child dentry holds reference on inode's alias, it makes
d_prune_aliases() do nothing.
Signed-off-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2862cfca
...@@ -1400,6 +1400,29 @@ static int __close_session(struct ceph_mds_client *mdsc, ...@@ -1400,6 +1400,29 @@ static int __close_session(struct ceph_mds_client *mdsc,
return request_close_session(mdsc, session); return request_close_session(mdsc, session);
} }
static bool drop_negative_children(struct dentry *dentry)
{
struct dentry *child;
bool all_negative = true;
if (!d_is_dir(dentry))
goto out;
spin_lock(&dentry->d_lock);
list_for_each_entry(child, &dentry->d_subdirs, d_child) {
if (d_really_is_positive(child)) {
all_negative = false;
break;
}
}
spin_unlock(&dentry->d_lock);
if (all_negative)
shrink_dcache_parent(dentry);
out:
return all_negative;
}
/* /*
* Trim old(er) caps. * Trim old(er) caps.
* *
...@@ -1445,16 +1468,27 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) ...@@ -1445,16 +1468,27 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
if ((used | wanted) & ~oissued & mine) if ((used | wanted) & ~oissued & mine)
goto out; /* we need these caps */ goto out; /* we need these caps */
session->s_trim_caps--;
if (oissued) { if (oissued) {
/* we aren't the only cap.. just remove us */ /* we aren't the only cap.. just remove us */
__ceph_remove_cap(cap, true); __ceph_remove_cap(cap, true);
session->s_trim_caps--;
} else { } else {
struct dentry *dentry;
/* try dropping referring dentries */ /* try dropping referring dentries */
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
dentry = d_find_any_alias(inode);
if (dentry && drop_negative_children(dentry)) {
int count;
dput(dentry);
d_prune_aliases(inode); d_prune_aliases(inode);
count = atomic_read(&inode->i_count);
if (count == 1)
session->s_trim_caps--;
dout("trim_caps_cb %p cap %p pruned, count now %d\n", dout("trim_caps_cb %p cap %p pruned, count now %d\n",
inode, cap, atomic_read(&inode->i_count)); inode, cap, count);
} else {
dput(dentry);
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment