函数源码

Linux Kernel

v5.5.9

Brick Technologies Co., Ltd

Source File:mm\memcontrol.c Create Date:2022-07-27 17:45:32
首页 Copyright©Brick

3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
                        gfp_t gfp_mask,
                        unsigned long *total_scanned)
{
    unsigned long nr_reclaimed = 0;
    struct mem_cgroup_per_node *mz, *next_mz = NULL;
    unsigned long reclaimed;
    int loop = 0;
    struct mem_cgroup_tree_per_node *mctz;
    unsigned long excess;
    unsigned long nr_scanned;
 
    if (order > 0)
        return 0;
 
    mctz = soft_limit_tree_node(pgdat->node_id);
 
    /*
     * Do not even bother to check the largest node if the root
     * is empty. Do it lockless to prevent lock bouncing. Races
     * are acceptable as soft limit is best effort anyway.
     */
    if (!mctz || RB_EMPTY_ROOT(&mctz->rb_root))
        return 0;
 
    /*
     * This loop can run a while, specially if mem_cgroup's continuously
     * keep exceeding their soft limit and putting the system under
     * pressure
     */
    do {
        if (next_mz)
            mz = next_mz;
        else
            mz = mem_cgroup_largest_soft_limit_node(mctz);
        if (!mz)
            break;
 
        nr_scanned = 0;
        reclaimed = mem_cgroup_soft_reclaim(mz->memcg, pgdat,
                            gfp_mask, &nr_scanned);
        nr_reclaimed += reclaimed;
        *total_scanned += nr_scanned;
        spin_lock_irq(&mctz->lock);
        __mem_cgroup_remove_exceeded(mz, mctz);
 
        /*
         * If we failed to reclaim anything from this memory cgroup
         * it is time to move on to the next cgroup
         */
        next_mz = NULL;
        if (!reclaimed)
            next_mz = __mem_cgroup_largest_soft_limit_node(mctz);
 
        excess = soft_limit_excess(mz->memcg);
        /*
         * One school of thought says that we should not add
         * back the node to the tree if reclaim returns 0.
         * But our reclaim could return 0, simply because due
         * to priority we are exposing a smaller subset of
         * memory to reclaim from. Consider this as a longer
         * term TODO.
         */
        /* If excess == 0, no tree ops */
        __mem_cgroup_insert_exceeded(mz, mctz, excess);
        spin_unlock_irq(&mctz->lock);
        css_put(&mz->memcg->css);
        loop++;
        /*
         * Could not reclaim anything and there are no more
         * mem cgroups to try or we seem to be looping without
         * reclaiming anything.
         */
        if (!nr_reclaimed &&
            (next_mz == NULL ||
            loop > MEM_CGROUP_MAX_SOFT_LIMIT_RECLAIM_LOOPS))
            break;
    } while (!nr_reclaimed);
    if (next_mz)
        css_put(&next_mz->memcg->css);
    return nr_reclaimed;
}