lkml.org 
[lkml]   [2017]   [Dec]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 022/178] ceph: drop negative child dentries before try pruning inodes alias
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Yan, Zheng <zyan@redhat.com>

    commit 040d786032bf59002d374b86d75b04d97624005c upstream.

    Negative child dentry holds reference on inode's alias, it makes
    d_prune_aliases() do nothing.

    Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
    Reviewed-by: Jeff Layton <jlayton@redhat.com>
    Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/ceph/mds_client.c | 42 ++++++++++++++++++++++++++++++++++++++----
    1 file changed, 38 insertions(+), 4 deletions(-)

    --- a/fs/ceph/mds_client.c
    +++ b/fs/ceph/mds_client.c
    @@ -1428,6 +1428,29 @@ static int __close_session(struct ceph_m
    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.
    *
    @@ -1473,16 +1496,27 @@ static int trim_caps_cb(struct inode *in
    if ((used | wanted) & ~oissued & mine)
    goto out; /* we need these caps */

    - session->s_trim_caps--;
    if (oissued) {
    /* we aren't the only cap.. just remove us */
    __ceph_remove_cap(cap, true);
    + session->s_trim_caps--;
    } else {
    + struct dentry *dentry;
    /* try dropping referring dentries */
    spin_unlock(&ci->i_ceph_lock);
    - d_prune_aliases(inode);
    - dout("trim_caps_cb %p cap %p pruned, count now %d\n",
    - inode, cap, atomic_read(&inode->i_count));
    + dentry = d_find_any_alias(inode);
    + if (dentry && drop_negative_children(dentry)) {
    + int count;
    + dput(dentry);
    + 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",
    + inode, cap, count);
    + } else {
    + dput(dentry);
    + }
    return 0;
    }


    \
     
     \ /
      Last update: 2017-12-18 17:57    [W:4.660 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site