lkml.org 
[lkml]   [2023]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v2 38/39] codetag: debug: introduce OBJEXTS_ALLOC_FAIL to mark failed slab_ext allocations
    From
    If slabobj_ext vector allocation for a slab object fails and later on it
    succeeds for another object in the same slab, the slabobj_ext for the
    original object will be NULL and will be flagged in case when
    CONFIG_MEM_ALLOC_PROFILING_DEBUG is enabled.
    Mark failed slabobj_ext vector allocations using a new objext_flags flag
    stored in the lower bits of slab->obj_exts. When new allocation succeeds
    it marks all tag references in the same slabobj_ext vector as empty to
    avoid warnings implemented by CONFIG_MEM_ALLOC_PROFILING_DEBUG checks.

    Signed-off-by: Suren Baghdasaryan <surenb@google.com>
    ---
    include/linux/memcontrol.h | 4 +++-
    mm/slab.h | 25 +++++++++++++++++++++++++
    mm/slab_common.c | 22 +++++++++++++++-------
    3 files changed, 43 insertions(+), 8 deletions(-)

    diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
    index 853a24b5f713..6b680ca424e3 100644
    --- a/include/linux/memcontrol.h
    +++ b/include/linux/memcontrol.h
    @@ -363,8 +363,10 @@ enum page_memcg_data_flags {
    #endif /* CONFIG_MEMCG */

    enum objext_flags {
    + /* slabobj_ext vector failed to allocate */
    + OBJEXTS_ALLOC_FAIL = __FIRST_OBJEXT_FLAG,
    /* the next bit after the last actual flag */
    - __NR_OBJEXTS_FLAGS = __FIRST_OBJEXT_FLAG,
    + __NR_OBJEXTS_FLAGS = (__FIRST_OBJEXT_FLAG << 1),
    };

    #define OBJEXTS_FLAGS_MASK (__NR_OBJEXTS_FLAGS - 1)
    diff --git a/mm/slab.h b/mm/slab.h
    index 45216bad34b8..1736268892e6 100644
    --- a/mm/slab.h
    +++ b/mm/slab.h
    @@ -474,9 +474,34 @@ static inline void mark_objexts_empty(struct slabobj_ext *obj_exts)
    }
    }

    +static inline void mark_failed_objexts_alloc(struct slab *slab)
    +{
    + slab->obj_exts = OBJEXTS_ALLOC_FAIL;
    +}
    +
    +static inline void handle_failed_objexts_alloc(unsigned long obj_exts,
    + struct slabobj_ext *vec, unsigned int objects)
    +{
    + /*
    + * If vector previously failed to allocate then we have live
    + * objects with no tag reference. Mark all references in this
    + * vector as empty to avoid warnings later on.
    + */
    + if (obj_exts & OBJEXTS_ALLOC_FAIL) {
    + unsigned int i;
    +
    + for (i = 0; i < objects; i++)
    + set_codetag_empty(&vec[i].ref);
    + }
    +}
    +
    +
    #else /* CONFIG_MEM_ALLOC_PROFILING_DEBUG */

    static inline void mark_objexts_empty(struct slabobj_ext *obj_exts) {}
    +static inline void mark_failed_objexts_alloc(struct slab *slab) {}
    +static inline void handle_failed_objexts_alloc(unsigned long obj_exts,
    + struct slabobj_ext *vec, unsigned int objects) {}

    #endif /* CONFIG_MEM_ALLOC_PROFILING_DEBUG */

    diff --git a/mm/slab_common.c b/mm/slab_common.c
    index db2cd7afc353..cea73314f919 100644
    --- a/mm/slab_common.c
    +++ b/mm/slab_common.c
    @@ -218,29 +218,37 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
    gfp_t gfp, bool new_slab)
    {
    unsigned int objects = objs_per_slab(s, slab);
    - unsigned long obj_exts;
    - void *vec;
    + unsigned long new_exts;
    + unsigned long old_exts;
    + struct slabobj_ext *vec;

    gfp &= ~OBJCGS_CLEAR_MASK;
    /* Prevent recursive extension vector allocation */
    gfp |= __GFP_NO_OBJ_EXT;
    vec = kcalloc_node(objects, sizeof(struct slabobj_ext), gfp,
    slab_nid(slab));
    - if (!vec)
    + if (!vec) {
    + /* Mark vectors which failed to allocate */
    + if (new_slab)
    + mark_failed_objexts_alloc(slab);
    +
    return -ENOMEM;
    + }

    - obj_exts = (unsigned long)vec;
    + new_exts = (unsigned long)vec;
    #ifdef CONFIG_MEMCG
    - obj_exts |= MEMCG_DATA_OBJEXTS;
    + new_exts |= MEMCG_DATA_OBJEXTS;
    #endif
    + old_exts = slab->obj_exts;
    + handle_failed_objexts_alloc(old_exts, vec, objects);
    if (new_slab) {
    /*
    * If the slab is brand new and nobody can yet access its
    * obj_exts, no synchronization is required and obj_exts can
    * be simply assigned.
    */
    - slab->obj_exts = obj_exts;
    - } else if (cmpxchg(&slab->obj_exts, 0, obj_exts)) {
    + slab->obj_exts = new_exts;
    + } else if (cmpxchg(&slab->obj_exts, old_exts, new_exts) != old_exts) {
    /*
    * If the slab is already in use, somebody can allocate and
    * assign slabobj_exts in parallel. In this case the existing
    --
    2.42.0.758.gaed0368e0e-goog
    \
     
     \ /
      Last update: 2023-10-24 15:53    [W:6.048 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site