lkml.org 
[lkml]   [2020]   [Apr]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 23/24] rcu: Introduce 1 arg kvfree_rcu() interface
    Date
    Make it possible to pass one or two arguments to the
    kvfree_rcu() macro what corresponds to either headless
    case or not, so it becomes a bit versatile.

    As a result we obtain two ways of using that macro,
    below are two examples:

    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);

    Last one, we name it headless variant, only needs one
    argument, means it does not require any rcu_head to be
    present within the type of ptr.

    There is a restriction the (b) context has to fall into
    might_sleep() annotation. To check that, please activate
    the CONFIG_DEBUG_ATOMIC_SLEEP option in your kernel.

    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-04-28 23:00    [W:7.743 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site