lkml.org 
[lkml]   [2011]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 3/4] limit nr_dentries per superblock
    Date
    This patch lays the foundation for us to limit the dcache size.
    Each super block can have only a maximum amount of dentries under its
    sub-tree. Allocation fails if we we're over limit and the cache
    can't be pruned to free up space for the newcomers.

    Signed-off-by: Glauber Costa <glommer@parallels.com>
    CC: Dave Chinner <david@fromorbit.com>
    CC: Eric Dumazet <eric.dumazet@gmail.com>
    ---
    fs/dcache.c | 28 ++++++++++++++++++++++++++++
    fs/super.c | 1 +
    include/linux/fs.h | 1 +
    3 files changed, 30 insertions(+), 0 deletions(-)

    diff --git a/fs/dcache.c b/fs/dcache.c
    index 815d9fd..ddd02a2 100644
    --- a/fs/dcache.c
    +++ b/fs/dcache.c
    @@ -1180,6 +1180,31 @@ void shrink_dcache_parent(struct dentry * parent)
    }
    EXPORT_SYMBOL(shrink_dcache_parent);

    +static inline int dcache_mem_check(struct super_block *sb)
    +{
    + struct shrink_control sc = {
    + .gfp_mask = GFP_KERNEL,
    + };
    +
    + if (sb->s_nr_dentry_max == INT_MAX)
    + return 0;
    +
    + do {
    + int nr_dentry;
    +
    + nr_dentry = percpu_counter_read_positive(&sb->s_nr_dentry);
    + if (nr_dentry > sb->s_nr_dentry_max)
    + nr_dentry =
    + percpu_counter_sum_positive(&sb->s_nr_dentry);
    + if (nr_dentry < sb->s_nr_dentry_max)
    + return 0;
    +
    + /* nr_pages = 1, lru_pages = 0 should get delta ~ 2 */
    + } while (shrink_one_shrinker(&sb->s_shrink, &sc, 1, 0));
    +
    + return -ENOMEM;
    +}
    +
    /**
    * __d_alloc - allocate a dcache entry
    * @sb: filesystem it will belong to
    @@ -1195,6 +1220,9 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
    struct dentry *dentry;
    char *dname;

    + if (dcache_mem_check(sb))
    + return NULL;
    +
    dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
    if (!dentry)
    return NULL;
    diff --git a/fs/super.c b/fs/super.c
    index e95ac4f..3db40fb 100644
    --- a/fs/super.c
    +++ b/fs/super.c
    @@ -121,6 +121,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
    }

    percpu_counter_init(&s->s_nr_dentry, 0);
    + s->s_nr_dentry_max = INT_MAX;

    #ifdef CONFIG_SMP
    s->s_files = alloc_percpu(struct list_head);
    diff --git a/include/linux/fs.h b/include/linux/fs.h
    index 8150f52..bc773c3 100644
    --- a/include/linux/fs.h
    +++ b/include/linux/fs.h
    @@ -1400,6 +1400,7 @@ struct super_block {
    int s_nr_dentry_unused; /* # of dentry on lru */

    struct percpu_counter s_nr_dentry; /* # of dentry on this sb */
    + int s_nr_dentry_max; /* max # of dentry on this sb*/

    /* s_inode_lru_lock protects s_inode_lru and s_nr_inodes_unused */
    spinlock_t s_inode_lru_lock ____cacheline_aligned_in_smp;
    --
    1.7.6


    \
     
     \ /
      Last update: 2011-08-14 18:17    [W:0.021 / U:60.856 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site