lkml.org 
[lkml]   [2020]   [May]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 15/16] rcu: Introduce single argument kvfree_rcu() interface
    Date
    Make kvfree_rcu() capable of freeing objects that will not
    embed an rcu_head within it. This saves storage overhead in
    such objects. Reclaiming headless objects this way requires
    only a single argument (pointer to the object).

    After this patch, there are two ways to use kvfree_rcu():

    a) kvfree_rcu(ptr, rhf);
    struct X {
    struct rcu_head rhf;
    unsigned char data[100];
    };

    void *ptr = kvmalloc(sizeof(struct X), GFP_KERNEL);
    if (ptr)
    kvfree_rcu(ptr, rhf);

    b) kvfree_rcu(ptr);
    void *ptr = kvmalloc(some_bytes, GFP_KERNEL);
    if (ptr)
    kvfree_rcu(ptr);

    Note that the headless usage (example b) can only be used in a code
    that can sleep. This is enforced by the CONFIG_DEBUG_ATOMIC_SLEEP
    option.

    Co-developed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
    Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
    Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
    ---
    include/linux/rcupdate.h | 38 ++++++++++++++++++++++++++++++++++----
    1 file changed, 34 insertions(+), 4 deletions(-)

    diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
    index 51b26ab02878..d15d46db61f7 100644
    --- a/include/linux/rcupdate.h
    +++ b/include/linux/rcupdate.h
    @@ -877,12 +877,42 @@ do { \

    /**
    * kvfree_rcu() - kvfree an object after a grace period.
    - * @ptr: pointer to kvfree
    - * @rhf: the name of the struct rcu_head within the type of @ptr.
    *
    - * Same as kfree_rcu(), just simple alias.
    + * This macro consists of one or two arguments and it is
    + * based on whether an object is head-less or not. If it
    + * has a head then a semantic stays the same as it used
    + * to be before:
    + *
    + * kvfree_rcu(ptr, rhf);
    + *
    + * where @ptr is a pointer to kvfree(), @rhf is the name
    + * of the rcu_head structure within the type of @ptr.
    + *
    + * When it comes to head-less variant, only one argument
    + * is passed and that is just a pointer which has to be
    + * freed after a grace period. Therefore the semantic is
    + *
    + * kvfree_rcu(ptr);
    + *
    + * where @ptr is a pointer to kvfree().
    + *
    + * Please note, head-less way of freeing is permitted to
    + * use from a context that has to follow might_sleep()
    + * annotation. Otherwise, please switch and embed the
    + * rcu_head structure within the type of @ptr.
    */
    -#define kvfree_rcu(ptr, rhf) kfree_rcu(ptr, rhf)
    +#define kvfree_rcu(...) KVFREE_GET_MACRO(__VA_ARGS__, \
    + kvfree_rcu_arg_2, kvfree_rcu_arg_1)(__VA_ARGS__)
    +
    +#define KVFREE_GET_MACRO(_1, _2, NAME, ...) NAME
    +#define kvfree_rcu_arg_2(ptr, rhf) kfree_rcu(ptr, rhf)
    +#define kvfree_rcu_arg_1(ptr) \
    +do { \
    + typeof(ptr) ___p = (ptr); \
    + \
    + if (___p) \
    + kvfree_call_rcu(NULL, (rcu_callback_t) (___p)); \
    +} while (0)

    /*
    * Place this after a lock-acquisition primitive to guarantee that
    --
    2.20.1
    \
     
     \ /
      Last update: 2020-05-25 23:49    [W:4.309 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site