• Vlastimil Babka's avatar
    mm/slub: Convert most struct page to struct slab by spatch · bb192ed9
    Vlastimil Babka authored
    The majority of conversion from struct page to struct slab in SLUB
    internals can be delegated to a coccinelle semantic patch. This includes
    renaming of variables with 'page' in name to 'slab', and similar.
    
    Big thanks to Julia Lawall and Luis Chamberlain for help with
    coccinelle.
    
    // Options: --include-headers --no-includes --smpl-spacing include/linux/slub_def.h mm/slub.c
    // Note: needs coccinelle 1.1.1 to avoid breaking whitespace, and ocaml for the
    // embedded script
    
    // build list of functions to exclude from applying the next rule
    @initialize:ocaml@
    @@
    
    let ok_function p =
      not (List.mem (List.hd p).current_element ["nearest_obj";"obj_to_index";"objs_per_slab_page";"__slab_lock";"__slab_unlock";"free_nonslab_page";"kmalloc_large_node"])
    
    // convert the type from struct page to struct page in all functions except the
    // list from previous rule
    // this also affects struct kmem_cache_cpu, but that's ok
    @@
    position p : script:ocaml() { ok_function p };
    @@
    
    - struct page@p
    + struct slab
    
    // in struct kmem_cache_cpu, change the name from page to slab
    // the type was already converted by the previous rule
    @@
    @@
    
    struct kmem_cache_cpu {
    ...
    -struct slab *page;
    +struct slab *slab;
    ...
    }
    
    // there are many places that use c->page which is now c->slab after the
    // previous rule
    @@
    struct kmem_cache_cpu *c;
    @@
    
    -c->page
    +c->slab
    
    @@
    @@
    
    struct kmem_cache {
    ...
    - unsigned int cpu_partial_pages;
    + unsigned int cpu_partial_slabs;
    ...
    }
    
    @@
    struct kmem_cache *s;
    @@
    
    - s->cpu_partial_pages
    + s->cpu_partial_slabs
    
    @@
    @@
    
    static void
    - setup_page_debug(
    + setup_slab_debug(
     ...)
     {...}
    
    @@
    @@
    
    - setup_page_debug(
    + setup_slab_debug(
     ...);
    
    // for all functions (with exceptions), change any "struct slab *page"
    // parameter to "struct slab *slab" in the signature, and generally all
    // occurences of "page" to "slab" in the body - with some special cases.
    
    @@
    identifier fn !~ "free_nonslab_page|obj_to_index|objs_per_slab_page|nearest_obj";
    @@
     fn(...,
    -   struct slab *page
    +   struct slab *slab
        ,...)
     {
    <...
    - page
    + slab
    ...>
     }
    
    // similar to previous but the param is called partial_page
    @@
    identifier fn;
    @@
    
     fn(...,
    -   struct slab *partial_page
    +   struct slab *partial_slab
        ,...)
     {
    <...
    - partial_page
    + partial_slab
    ...>
     }
    
    // similar to previous but for functions that take pointer to struct page ptr
    @@
    identifier fn;
    @@
    
     fn(...,
    -   struct slab **ret_page
    +   struct slab **ret_slab
        ,...)
     {
    <...
    - ret_page
    + ret_slab
    ...>
     }
    
    // functions converted by previous rules that were temporarily called using
    // slab_page(E) so we want to remove the wrapper now that they accept struct
    // slab ptr directly
    @@
    identifier fn =~ "slab_free|do_slab_free";
    expression E;
    @@
    
     fn(...,
    - slab_page(E)
    + E
      ,...)
    
    // similar to previous but for another pattern
    @@
    identifier fn =~ "slab_pad_check|check_object";
    @@
    
     fn(...,
    - folio_page(folio, 0)
    + slab
      ,...)
    
    // functions that were returning struct page ptr and now will return struct
    // slab ptr, including slab_page() wrapper removal
    @@
    identifier fn =~ "allocate_slab|new_slab";
    expression E;
    @@
    
     static
    -struct slab *
    +struct slab *
     fn(...)
     {
    <...
    - slab_page(E)
    + E
    ...>
     }
    
    // rename any former struct page * declarations
    @@
    @@
    
    struct slab *
    (
    - page
    + slab
    |
    - partial_page
    + partial_slab
    |
    - oldpage
    + oldslab
    )
    ;
    
    // this has to be separate from previous rule as page and page2 appear at the
    // same line
    @@
    @@
    
    struct slab *
    -page2
    +slab2
    ;
    
    // similar but with initial assignment
    @@
    expression E;
    @@
    
    struct slab *
    (
    - page
    + slab
    |
    - flush_page
    + flush_slab
    |
    - discard_page
    + slab_to_discard
    |
    - page_to_unfreeze
    + slab_to_unfreeze
    )
    = E;
    
    // convert most of struct page to struct slab usage inside functions (with
    // exceptions), including specific variable renames
    @@
    identifier fn !~ "nearest_obj|obj_to_index|objs_per_slab_page|__slab_(un)*lock|__free_slab|free_nonslab_page|kmalloc_large_node";
    expression E;
    @@
    
     fn(...)
     {
    <...
    (
    - int pages;
    + int slabs;
    |
    - int pages = E;
    + int slabs = E;
    |
    - page
    + slab
    |
    - flush_page
    + flush_slab
    |
    - partial_page
    + partial_slab
    |
    - oldpage->pages
    + oldslab->slabs
    |
    - oldpage
    + oldslab
    |
    - unsigned int nr_pages;
    + unsigned int nr_slabs;
    |
    - nr_pages
    + nr_slabs
    |
    - unsigned int partial_pages = E;
    + unsigned int partial_slabs = E;
    |
    - partial_pages
    + partial_slabs
    )
    ...>
     }
    
    // this has to be split out from the previous rule so that lines containing
    // multiple matching changes will be fully converted
    @@
    identifier fn !~ "nearest_obj|obj_to_index|objs_per_slab_page|__slab_(un)*lock|__free_slab|free_nonslab_page|kmalloc_large_node";
    @@
    
     fn(...)
     {
    <...
    (
    - slab->pages
    + slab->slabs
    |
    - pages
    + slabs
    |
    - page2
    + slab2
    |
    - discard_page
    + slab_to_discard
    |
    - page_to_unfreeze
    + slab_to_unfreeze
    )
    ...>
     }
    
    // after we simply changed all occurences of page to slab, some usages need
    // adjustment for slab-specific functions, or use slab_page() wrapper
    @@
    identifier fn !~ "nearest_obj|obj_to_index|objs_per_slab_page|__slab_(un)*lock|__free_slab|free_nonslab_page|kmalloc_large_node";
    @@
    
     fn(...)
     {
    <...
    (
    - page_slab(slab)
    + slab
    |
    - kasan_poison_slab(slab)
    + kasan_poison_slab(slab_page(slab))
    |
    - page_address(slab)
    + slab_address(slab)
    |
    - page_size(slab)
    + slab_size(slab)
    |
    - PageSlab(slab)
    + folio_test_slab(slab_folio(slab))
    |
    - page_to_nid(slab)
    + slab_nid(slab)
    |
    - compound_order(slab)
    + slab_order(slab)
    )
    ...>
     }
    Signed-off-by: default avatarVlastimil Babka <vbabka@suse.cz>
    Reviewed-by: default avatarRoman Gushchin <guro@fb.com>
    Reviewed-by: default avatarHyeonggon Yoo <42.hyeyoo@gmail.com>
    Tested-by: default avatarHyeonggon Yoo <42.hyeyoo@gmail.com>
    Cc: Julia Lawall <julia.lawall@inria.fr>
    Cc: Luis Chamberlain <mcgrof@kernel.org>
    bb192ed9
slub.c 154 KB