ceph: drop negative child dentries before try pruning inode's alias
Negative child dentry holds reference on inode's alias, it makes d_prune_aliases() do nothing. Cc: stable@vger.kernel.org Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
ae64f9bd1d
commit
040d786032
|
@ -1440,6 +1440,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.
|
||||||
*
|
*
|
||||||
|
@ -1490,16 +1513,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue