* [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c
@ 2017-12-21 22:32 rao.shoaib
2017-12-22 1:17 ` Boqun Feng
0 siblings, 1 reply; 6+ messages in thread
From: rao.shoaib @ 2017-12-21 22:32 UTC (permalink / raw)
Cc: paulmck, brouer, linux-mm, Rao Shoaib
From: Rao Shoaib <rao.shoaib@oracle.com>
This patch moves kfree_call_rcu() and related macros out of rcu code.
A new function call_rcu_lazy() is created for calling __call_rcu() with
the lazy flag. kfree_call_rcu() in the tiny implementation remains unchanged.
V2: Addresses the noise generated by checkpatch
Signed-off-by: Rao Shoaib <rao.shoaib@oracle.com>
---
include/linux/rcupdate.h | 43 +++----------------------------------------
include/linux/rcutree.h | 2 --
include/linux/slab.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
kernel/rcu/tree.c | 24 ++++++++++--------------
mm/slab_common.c | 10 ++++++++++
5 files changed, 67 insertions(+), 56 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index a6ddc42..23ed728 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -55,6 +55,9 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
#define call_rcu call_rcu_sched
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+/* only for use by kfree_call_rcu() */
+void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func);
+
void call_rcu_bh(struct rcu_head *head, rcu_callback_t func);
void call_rcu_sched(struct rcu_head *head, rcu_callback_t func);
void synchronize_sched(void);
@@ -838,45 +841,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
/*
- * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
- */
-#define __kfree_rcu(head, offset) \
- do { \
- BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
- kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
- } while (0)
-
-/**
- * kfree_rcu() - kfree an object after a grace period.
- * @ptr: pointer to kfree
- * @rcu_head: the name of the struct rcu_head within the type of @ptr.
- *
- * Many rcu callbacks functions just call kfree() on the base structure.
- * These functions are trivial, but their size adds up, and furthermore
- * when they are used in a kernel module, that module must invoke the
- * high-latency rcu_barrier() function at module-unload time.
- *
- * The kfree_rcu() function handles this issue. Rather than encoding a
- * function address in the embedded rcu_head structure, kfree_rcu() instead
- * encodes the offset of the rcu_head structure within the base structure.
- * Because the functions are not allowed in the low-order 4096 bytes of
- * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
- * If the offset is larger than 4095 bytes, a compile-time error will
- * be generated in __kfree_rcu(). If this error is triggered, you can
- * either fall back to use of call_rcu() or rearrange the structure to
- * position the rcu_head structure into the first 4096 bytes.
- *
- * Note that the allowable offset might decrease in the future, for example,
- * to allow something like kmem_cache_free_rcu().
- *
- * The BUILD_BUG_ON check must not involve any function calls, hence the
- * checks are done in macros here.
- */
-#define kfree_rcu(ptr, rcu_head) \
- __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
-
-
-/*
* Place this after a lock-acquisition primitive to guarantee that
* an UNLOCK+LOCK pair acts as a full barrier. This guarantee applies
* if the UNLOCK and LOCK are executed by the same CPU or if the
@@ -888,5 +852,4 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define smp_mb__after_unlock_lock() do { } while (0)
#endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
-
#endif /* __LINUX_RCUPDATE_H */
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 37d6fd3..7746b19 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -48,8 +48,6 @@ void synchronize_rcu_bh(void);
void synchronize_sched_expedited(void);
void synchronize_rcu_expedited(void);
-void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
-
/**
* synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period
*
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 50697a1..a71f6a78 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -342,6 +342,50 @@ void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
void kmem_cache_free(struct kmem_cache *, void *);
+void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
+
+/* Helper macro for kfree_rcu() to prevent argument-expansion eyestrain. */
+#define __kfree_rcu(head, offset) \
+ do { \
+ unsigned long __o = (unsigned long)offset; \
+ BUILD_BUG_ON(!__is_kfree_rcu_offset(__o)); \
+ kfree_call_rcu(head, (rcu_callback_t)(__o)); \
+ } while (0)
+
+/**
+ * kfree_rcu() - kfree an object after a grace period.
+ * @ptr: pointer to kfree
+ * @rcu_head: the name of the struct rcu_head within the type of @ptr.
+ *
+ * Many rcu callbacks functions just call kfree() on the base structure.
+ * These functions are trivial, but their size adds up, and furthermore
+ * when they are used in a kernel module, that module must invoke the
+ * high-latency rcu_barrier() function at module-unload time.
+ *
+ * The kfree_rcu() function handles this issue. Rather than encoding a
+ * function address in the embedded rcu_head structure, kfree_rcu() instead
+ * encodes the offset of the rcu_head structure within the base structure.
+ * Because the functions are not allowed in the low-order 4096 bytes of
+ * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
+ * If the offset is larger than 4095 bytes, a compile-time error will
+ * be generated in __kfree_rcu(). If this error is triggered, you can
+ * either fall back to use of call_rcu() or rearrange the structure to
+ * position the rcu_head structure into the first 4096 bytes.
+ *
+ * Note that the allowable offset might decrease in the future, for example,
+ * to allow something like kmem_cache_free_rcu().
+ *
+ * The BUILD_BUG_ON check must not involve any function calls, hence the
+ * checks are done in macros here.
+ */
+#define kfree_rcu(ptr, rcu_head_name) \
+ do { \
+ typeof(ptr) __ptr = ptr; \
+ unsigned long __off = offsetof(typeof(*(__ptr)), \
+ rcu_head_name); \
+ struct rcu_head *__rptr = (void *)__ptr + __off; \
+ __kfree_rcu(__rptr, __off); \
+ } while (0)
/*
* Bulk allocation and freeing operations. These are accelerated in an
* allocator specific way to avoid taking locks repeatedly or building
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index f9c0ca2..7d2830f 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3180,6 +3180,16 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
}
EXPORT_SYMBOL_GPL(call_rcu_sched);
+/* Queue an RCU callback for lazy invocation after a grace period.
+ * Currently there is no way of tagging the lazy RCU callbacks in the
+ * list of pending callbacks. Until then, this function may only be
+ * called from kfree_call_rcu().
+ */
+void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func)
+{
+ __call_rcu(head, func, &rcu_sched_state, -1, 1);
+}
+
/**
* call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
* @head: structure to be used for queueing the RCU updates.
@@ -3209,20 +3219,6 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
EXPORT_SYMBOL_GPL(call_rcu_bh);
/*
- * Queue an RCU callback for lazy invocation after a grace period.
- * This will likely be later named something like "call_rcu_lazy()",
- * but this change will require some way of tagging the lazy RCU
- * callbacks in the list of pending callbacks. Until then, this
- * function may only be called from __kfree_rcu().
- */
-void kfree_call_rcu(struct rcu_head *head,
- rcu_callback_t func)
-{
- __call_rcu(head, func, rcu_state_p, -1, 1);
-}
-EXPORT_SYMBOL_GPL(kfree_call_rcu);
-
-/*
* Because a context switch is a grace period for RCU-sched and RCU-bh,
* any blocking grace-period wait automatically implies a grace period
* if there is only one CPU online at any point time during execution
diff --git a/mm/slab_common.c b/mm/slab_common.c
index c8cb367..0d8a63b 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -1483,6 +1483,16 @@ void kzfree(const void *p)
}
EXPORT_SYMBOL(kzfree);
+/*
+ * Queue Memory to be freed by RCU after a grace period.
+ */
+void kfree_call_rcu(struct rcu_head *head,
+ rcu_callback_t func)
+{
+ call_rcu_lazy(head, func);
+}
+EXPORT_SYMBOL_GPL(kfree_call_rcu);
+
/* Tracepoints definitions. */
EXPORT_TRACEPOINT_SYMBOL(kmalloc);
EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
--
2.7.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c
2017-12-21 22:32 [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c rao.shoaib
@ 2017-12-22 1:17 ` Boqun Feng
2017-12-22 1:42 ` Paul E. McKenney
0 siblings, 1 reply; 6+ messages in thread
From: Boqun Feng @ 2017-12-22 1:17 UTC (permalink / raw)
To: rao.shoaib; +Cc: paulmck, brouer, linux-mm
[-- Attachment #1: Type: text/plain, Size: 10002 bytes --]
Hi Shoaib,
On Thu, Dec 21, 2017 at 02:32:50PM -0800, rao.shoaib@oracle.com wrote:
> From: Rao Shoaib <rao.shoaib@oracle.com>
>
> This patch moves kfree_call_rcu() and related macros out of rcu code.
> A new function call_rcu_lazy() is created for calling __call_rcu() with
> the lazy flag. kfree_call_rcu() in the tiny implementation remains unchanged.
>
Mind to explain why you want to do this in the commit log?
> V2: Addresses the noise generated by checkpatch
>
> Signed-off-by: Rao Shoaib <rao.shoaib@oracle.com>
> ---
> include/linux/rcupdate.h | 43 +++----------------------------------------
> include/linux/rcutree.h | 2 --
> include/linux/slab.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
> kernel/rcu/tree.c | 24 ++++++++++--------------
> mm/slab_common.c | 10 ++++++++++
> 5 files changed, 67 insertions(+), 56 deletions(-)
>
> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> index a6ddc42..23ed728 100644
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -55,6 +55,9 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
> #define call_rcu call_rcu_sched
> #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
>
> +/* only for use by kfree_call_rcu() */
> +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func);
> +
> void call_rcu_bh(struct rcu_head *head, rcu_callback_t func);
> void call_rcu_sched(struct rcu_head *head, rcu_callback_t func);
> void synchronize_sched(void);
> @@ -838,45 +841,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> #define __is_kfree_rcu_offset(offset) ((offset) < 4096)
>
> /*
> - * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
> - */
> -#define __kfree_rcu(head, offset) \
> - do { \
> - BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
> - kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
> - } while (0)
> -
> -/**
> - * kfree_rcu() - kfree an object after a grace period.
> - * @ptr: pointer to kfree
> - * @rcu_head: the name of the struct rcu_head within the type of @ptr.
> - *
> - * Many rcu callbacks functions just call kfree() on the base structure.
> - * These functions are trivial, but their size adds up, and furthermore
> - * when they are used in a kernel module, that module must invoke the
> - * high-latency rcu_barrier() function at module-unload time.
> - *
> - * The kfree_rcu() function handles this issue. Rather than encoding a
> - * function address in the embedded rcu_head structure, kfree_rcu() instead
> - * encodes the offset of the rcu_head structure within the base structure.
> - * Because the functions are not allowed in the low-order 4096 bytes of
> - * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> - * If the offset is larger than 4095 bytes, a compile-time error will
> - * be generated in __kfree_rcu(). If this error is triggered, you can
> - * either fall back to use of call_rcu() or rearrange the structure to
> - * position the rcu_head structure into the first 4096 bytes.
> - *
> - * Note that the allowable offset might decrease in the future, for example,
> - * to allow something like kmem_cache_free_rcu().
> - *
> - * The BUILD_BUG_ON check must not involve any function calls, hence the
> - * checks are done in macros here.
> - */
> -#define kfree_rcu(ptr, rcu_head) \
> - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
> -
> -
> -/*
> * Place this after a lock-acquisition primitive to guarantee that
> * an UNLOCK+LOCK pair acts as a full barrier. This guarantee applies
> * if the UNLOCK and LOCK are executed by the same CPU or if the
> @@ -888,5 +852,4 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> #define smp_mb__after_unlock_lock() do { } while (0)
> #endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
>
> -
> #endif /* __LINUX_RCUPDATE_H */
> diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
> index 37d6fd3..7746b19 100644
> --- a/include/linux/rcutree.h
> +++ b/include/linux/rcutree.h
> @@ -48,8 +48,6 @@ void synchronize_rcu_bh(void);
> void synchronize_sched_expedited(void);
> void synchronize_rcu_expedited(void);
>
> -void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> -
> /**
> * synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period
> *
> diff --git a/include/linux/slab.h b/include/linux/slab.h
> index 50697a1..a71f6a78 100644
> --- a/include/linux/slab.h
> +++ b/include/linux/slab.h
> @@ -342,6 +342,50 @@ void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
> void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
> void kmem_cache_free(struct kmem_cache *, void *);
>
> +void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> +
> +/* Helper macro for kfree_rcu() to prevent argument-expansion eyestrain. */
> +#define __kfree_rcu(head, offset) \
> + do { \
> + unsigned long __o = (unsigned long)offset; \
> + BUILD_BUG_ON(!__is_kfree_rcu_offset(__o)); \
> + kfree_call_rcu(head, (rcu_callback_t)(__o)); \
> + } while (0)
> +
> +/**
> + * kfree_rcu() - kfree an object after a grace period.
> + * @ptr: pointer to kfree
> + * @rcu_head: the name of the struct rcu_head within the type of @ptr.
So you already rename this parameter to 'rcu_head_name', and...
> + *
> + * Many rcu callbacks functions just call kfree() on the base structure.
> + * These functions are trivial, but their size adds up, and furthermore
> + * when they are used in a kernel module, that module must invoke the
> + * high-latency rcu_barrier() function at module-unload time.
> + *
> + * The kfree_rcu() function handles this issue. Rather than encoding a
> + * function address in the embedded rcu_head structure, kfree_rcu() instead
> + * encodes the offset of the rcu_head structure within the base structure.
> + * Because the functions are not allowed in the low-order 4096 bytes of
> + * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> + * If the offset is larger than 4095 bytes, a compile-time error will
> + * be generated in __kfree_rcu(). If this error is triggered, you can
> + * either fall back to use of call_rcu() or rearrange the structure to
> + * position the rcu_head structure into the first 4096 bytes.
> + *
> + * Note that the allowable offset might decrease in the future, for example,
> + * to allow something like kmem_cache_free_rcu().
> + *
> + * The BUILD_BUG_ON check must not involve any function calls, hence the
> + * checks are done in macros here.
> + */
> +#define kfree_rcu(ptr, rcu_head_name) \
> + do { \
> + typeof(ptr) __ptr = ptr; \
> + unsigned long __off = offsetof(typeof(*(__ptr)), \
> + rcu_head_name); \
> + struct rcu_head *__rptr = (void *)__ptr + __off; \
> + __kfree_rcu(__rptr, __off); \
> + } while (0)
why do you want to open code this?
> /*
> * Bulk allocation and freeing operations. These are accelerated in an
> * allocator specific way to avoid taking locks repeatedly or building
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index f9c0ca2..7d2830f 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -3180,6 +3180,16 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
> }
> EXPORT_SYMBOL_GPL(call_rcu_sched);
>
> +/* Queue an RCU callback for lazy invocation after a grace period.
> + * Currently there is no way of tagging the lazy RCU callbacks in the
> + * list of pending callbacks. Until then, this function may only be
> + * called from kfree_call_rcu().
> + */
> +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func)
> +{
> + __call_rcu(head, func, &rcu_sched_state, -1, 1);
Why do you switch this from rcu_state_p to rcu_sched_state? Have you
checked your changes don't break PREEMPT=y kernel? Did I miss something
subtle?
Regards,
Boqun
> +}
> +
> /**
> * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
> * @head: structure to be used for queueing the RCU updates.
> @@ -3209,20 +3219,6 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
> EXPORT_SYMBOL_GPL(call_rcu_bh);
>
> /*
> - * Queue an RCU callback for lazy invocation after a grace period.
> - * This will likely be later named something like "call_rcu_lazy()",
> - * but this change will require some way of tagging the lazy RCU
> - * callbacks in the list of pending callbacks. Until then, this
> - * function may only be called from __kfree_rcu().
> - */
> -void kfree_call_rcu(struct rcu_head *head,
> - rcu_callback_t func)
> -{
> - __call_rcu(head, func, rcu_state_p, -1, 1);
> -}
> -EXPORT_SYMBOL_GPL(kfree_call_rcu);
> -
> -/*
> * Because a context switch is a grace period for RCU-sched and RCU-bh,
> * any blocking grace-period wait automatically implies a grace period
> * if there is only one CPU online at any point time during execution
> diff --git a/mm/slab_common.c b/mm/slab_common.c
> index c8cb367..0d8a63b 100644
> --- a/mm/slab_common.c
> +++ b/mm/slab_common.c
> @@ -1483,6 +1483,16 @@ void kzfree(const void *p)
> }
> EXPORT_SYMBOL(kzfree);
>
> +/*
> + * Queue Memory to be freed by RCU after a grace period.
> + */
> +void kfree_call_rcu(struct rcu_head *head,
> + rcu_callback_t func)
> +{
> + call_rcu_lazy(head, func);
> +}
> +EXPORT_SYMBOL_GPL(kfree_call_rcu);
> +
> /* Tracepoints definitions. */
> EXPORT_TRACEPOINT_SYMBOL(kmalloc);
> EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
> --
> 2.7.4
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org. For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c
2017-12-22 1:17 ` Boqun Feng
@ 2017-12-22 1:42 ` Paul E. McKenney
2017-12-22 2:38 ` Boqun Feng
0 siblings, 1 reply; 6+ messages in thread
From: Paul E. McKenney @ 2017-12-22 1:42 UTC (permalink / raw)
To: Boqun Feng; +Cc: rao.shoaib, brouer, linux-mm
On Fri, Dec 22, 2017 at 09:17:04AM +0800, Boqun Feng wrote:
> Hi Shoaib,
>
> On Thu, Dec 21, 2017 at 02:32:50PM -0800, rao.shoaib@oracle.com wrote:
> > From: Rao Shoaib <rao.shoaib@oracle.com>
> >
> > This patch moves kfree_call_rcu() and related macros out of rcu code.
> > A new function call_rcu_lazy() is created for calling __call_rcu() with
> > the lazy flag. kfree_call_rcu() in the tiny implementation remains unchanged.
> >
>
> Mind to explain why you want to do this in the commit log?
I am too close to this one, so I need you guys to hash this out. ;-)
> > V2: Addresses the noise generated by checkpatch
> >
> > Signed-off-by: Rao Shoaib <rao.shoaib@oracle.com>
> > ---
> > include/linux/rcupdate.h | 43 +++----------------------------------------
> > include/linux/rcutree.h | 2 --
> > include/linux/slab.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
> > kernel/rcu/tree.c | 24 ++++++++++--------------
> > mm/slab_common.c | 10 ++++++++++
> > 5 files changed, 67 insertions(+), 56 deletions(-)
> >
> > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> > index a6ddc42..23ed728 100644
> > --- a/include/linux/rcupdate.h
> > +++ b/include/linux/rcupdate.h
> > @@ -55,6 +55,9 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
> > #define call_rcu call_rcu_sched
> > #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
> >
> > +/* only for use by kfree_call_rcu() */
> > +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func);
> > +
> > void call_rcu_bh(struct rcu_head *head, rcu_callback_t func);
> > void call_rcu_sched(struct rcu_head *head, rcu_callback_t func);
> > void synchronize_sched(void);
> > @@ -838,45 +841,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> > #define __is_kfree_rcu_offset(offset) ((offset) < 4096)
> >
> > /*
> > - * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
> > - */
> > -#define __kfree_rcu(head, offset) \
> > - do { \
> > - BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
> > - kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
> > - } while (0)
> > -
> > -/**
> > - * kfree_rcu() - kfree an object after a grace period.
> > - * @ptr: pointer to kfree
> > - * @rcu_head: the name of the struct rcu_head within the type of @ptr.
> > - *
> > - * Many rcu callbacks functions just call kfree() on the base structure.
> > - * These functions are trivial, but their size adds up, and furthermore
> > - * when they are used in a kernel module, that module must invoke the
> > - * high-latency rcu_barrier() function at module-unload time.
> > - *
> > - * The kfree_rcu() function handles this issue. Rather than encoding a
> > - * function address in the embedded rcu_head structure, kfree_rcu() instead
> > - * encodes the offset of the rcu_head structure within the base structure.
> > - * Because the functions are not allowed in the low-order 4096 bytes of
> > - * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> > - * If the offset is larger than 4095 bytes, a compile-time error will
> > - * be generated in __kfree_rcu(). If this error is triggered, you can
> > - * either fall back to use of call_rcu() or rearrange the structure to
> > - * position the rcu_head structure into the first 4096 bytes.
> > - *
> > - * Note that the allowable offset might decrease in the future, for example,
> > - * to allow something like kmem_cache_free_rcu().
> > - *
> > - * The BUILD_BUG_ON check must not involve any function calls, hence the
> > - * checks are done in macros here.
> > - */
> > -#define kfree_rcu(ptr, rcu_head) \
> > - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
> > -
> > -
> > -/*
> > * Place this after a lock-acquisition primitive to guarantee that
> > * an UNLOCK+LOCK pair acts as a full barrier. This guarantee applies
> > * if the UNLOCK and LOCK are executed by the same CPU or if the
> > @@ -888,5 +852,4 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> > #define smp_mb__after_unlock_lock() do { } while (0)
> > #endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
> >
> > -
> > #endif /* __LINUX_RCUPDATE_H */
> > diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
> > index 37d6fd3..7746b19 100644
> > --- a/include/linux/rcutree.h
> > +++ b/include/linux/rcutree.h
> > @@ -48,8 +48,6 @@ void synchronize_rcu_bh(void);
> > void synchronize_sched_expedited(void);
> > void synchronize_rcu_expedited(void);
> >
> > -void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> > -
> > /**
> > * synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period
> > *
> > diff --git a/include/linux/slab.h b/include/linux/slab.h
> > index 50697a1..a71f6a78 100644
> > --- a/include/linux/slab.h
> > +++ b/include/linux/slab.h
> > @@ -342,6 +342,50 @@ void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
> > void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
> > void kmem_cache_free(struct kmem_cache *, void *);
> >
> > +void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> > +
> > +/* Helper macro for kfree_rcu() to prevent argument-expansion eyestrain. */
> > +#define __kfree_rcu(head, offset) \
> > + do { \
> > + unsigned long __o = (unsigned long)offset; \
> > + BUILD_BUG_ON(!__is_kfree_rcu_offset(__o)); \
> > + kfree_call_rcu(head, (rcu_callback_t)(__o)); \
> > + } while (0)
> > +
> > +/**
> > + * kfree_rcu() - kfree an object after a grace period.
> > + * @ptr: pointer to kfree
> > + * @rcu_head: the name of the struct rcu_head within the type of @ptr.
>
> So you already rename this parameter to 'rcu_head_name', and...
>
> > + *
> > + * Many rcu callbacks functions just call kfree() on the base structure.
> > + * These functions are trivial, but their size adds up, and furthermore
> > + * when they are used in a kernel module, that module must invoke the
> > + * high-latency rcu_barrier() function at module-unload time.
> > + *
> > + * The kfree_rcu() function handles this issue. Rather than encoding a
> > + * function address in the embedded rcu_head structure, kfree_rcu() instead
> > + * encodes the offset of the rcu_head structure within the base structure.
> > + * Because the functions are not allowed in the low-order 4096 bytes of
> > + * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> > + * If the offset is larger than 4095 bytes, a compile-time error will
> > + * be generated in __kfree_rcu(). If this error is triggered, you can
> > + * either fall back to use of call_rcu() or rearrange the structure to
> > + * position the rcu_head structure into the first 4096 bytes.
> > + *
> > + * Note that the allowable offset might decrease in the future, for example,
> > + * to allow something like kmem_cache_free_rcu().
> > + *
> > + * The BUILD_BUG_ON check must not involve any function calls, hence the
> > + * checks are done in macros here.
> > + */
> > +#define kfree_rcu(ptr, rcu_head_name) \
> > + do { \
> > + typeof(ptr) __ptr = ptr; \
> > + unsigned long __off = offsetof(typeof(*(__ptr)), \
> > + rcu_head_name); \
> > + struct rcu_head *__rptr = (void *)__ptr + __off; \
> > + __kfree_rcu(__rptr, __off); \
> > + } while (0)
>
> why do you want to open code this?
He needs it to be a macro so that offsetof() will work properly.
> > /*
> > * Bulk allocation and freeing operations. These are accelerated in an
> > * allocator specific way to avoid taking locks repeatedly or building
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index f9c0ca2..7d2830f 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -3180,6 +3180,16 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
> > }
> > EXPORT_SYMBOL_GPL(call_rcu_sched);
> >
> > +/* Queue an RCU callback for lazy invocation after a grace period.
> > + * Currently there is no way of tagging the lazy RCU callbacks in the
> > + * list of pending callbacks. Until then, this function may only be
> > + * called from kfree_call_rcu().
> > + */
> > +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func)
> > +{
> > + __call_rcu(head, func, &rcu_sched_state, -1, 1);
>
> Why do you switch this from rcu_state_p to rcu_sched_state? Have you
> checked your changes don't break PREEMPT=y kernel? Did I miss something
> subtle?
Good catch, this would be a problem on PREEMPT=y kernels. I agree with
Boqun's implicit suggestion of using rcu_state_p.
Thanx, Paul
> Regards,
> Boqun
>
> > +}
> > +
> > /**
> > * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
> > * @head: structure to be used for queueing the RCU updates.
> > @@ -3209,20 +3219,6 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
> > EXPORT_SYMBOL_GPL(call_rcu_bh);
> >
> > /*
> > - * Queue an RCU callback for lazy invocation after a grace period.
> > - * This will likely be later named something like "call_rcu_lazy()",
> > - * but this change will require some way of tagging the lazy RCU
> > - * callbacks in the list of pending callbacks. Until then, this
> > - * function may only be called from __kfree_rcu().
> > - */
> > -void kfree_call_rcu(struct rcu_head *head,
> > - rcu_callback_t func)
> > -{
> > - __call_rcu(head, func, rcu_state_p, -1, 1);
> > -}
> > -EXPORT_SYMBOL_GPL(kfree_call_rcu);
> > -
> > -/*
> > * Because a context switch is a grace period for RCU-sched and RCU-bh,
> > * any blocking grace-period wait automatically implies a grace period
> > * if there is only one CPU online at any point time during execution
> > diff --git a/mm/slab_common.c b/mm/slab_common.c
> > index c8cb367..0d8a63b 100644
> > --- a/mm/slab_common.c
> > +++ b/mm/slab_common.c
> > @@ -1483,6 +1483,16 @@ void kzfree(const void *p)
> > }
> > EXPORT_SYMBOL(kzfree);
> >
> > +/*
> > + * Queue Memory to be freed by RCU after a grace period.
> > + */
> > +void kfree_call_rcu(struct rcu_head *head,
> > + rcu_callback_t func)
> > +{
> > + call_rcu_lazy(head, func);
> > +}
> > +EXPORT_SYMBOL_GPL(kfree_call_rcu);
> > +
> > /* Tracepoints definitions. */
> > EXPORT_TRACEPOINT_SYMBOL(kmalloc);
> > EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
> > --
> > 2.7.4
> >
> > --
> > To unsubscribe, send a message with 'unsubscribe linux-mm' in
> > the body to majordomo@kvack.org. For more info on Linux MM,
> > see: http://www.linux-mm.org/ .
> > Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c
2017-12-22 1:42 ` Paul E. McKenney
@ 2017-12-22 2:38 ` Boqun Feng
2017-12-22 2:53 ` Boqun Feng
2018-01-02 20:18 ` Paul E. McKenney
0 siblings, 2 replies; 6+ messages in thread
From: Boqun Feng @ 2017-12-22 2:38 UTC (permalink / raw)
To: Paul E. McKenney; +Cc: rao.shoaib, brouer, linux-mm
[-- Attachment #1: Type: text/plain, Size: 11910 bytes --]
On Thu, Dec 21, 2017 at 05:42:12PM -0800, Paul E. McKenney wrote:
> On Fri, Dec 22, 2017 at 09:17:04AM +0800, Boqun Feng wrote:
> > Hi Shoaib,
> >
> > On Thu, Dec 21, 2017 at 02:32:50PM -0800, rao.shoaib@oracle.com wrote:
> > > From: Rao Shoaib <rao.shoaib@oracle.com>
> > >
> > > This patch moves kfree_call_rcu() and related macros out of rcu code.
> > > A new function call_rcu_lazy() is created for calling __call_rcu() with
> > > the lazy flag. kfree_call_rcu() in the tiny implementation remains unchanged.
> > >
> >
> > Mind to explain why you want to do this in the commit log?
>
> I am too close to this one, so I need you guys to hash this out. ;-)
>
I think simply improving the modularity is OK, but it's better to have
some words in the commit log ;-)
> > > V2: Addresses the noise generated by checkpatch
> > >
> > > Signed-off-by: Rao Shoaib <rao.shoaib@oracle.com>
> > > ---
> > > include/linux/rcupdate.h | 43 +++----------------------------------------
> > > include/linux/rcutree.h | 2 --
> > > include/linux/slab.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
> > > kernel/rcu/tree.c | 24 ++++++++++--------------
> > > mm/slab_common.c | 10 ++++++++++
> > > 5 files changed, 67 insertions(+), 56 deletions(-)
> > >
> > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> > > index a6ddc42..23ed728 100644
> > > --- a/include/linux/rcupdate.h
> > > +++ b/include/linux/rcupdate.h
> > > @@ -55,6 +55,9 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
> > > #define call_rcu call_rcu_sched
> > > #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
> > >
> > > +/* only for use by kfree_call_rcu() */
> > > +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func);
> > > +
> > > void call_rcu_bh(struct rcu_head *head, rcu_callback_t func);
> > > void call_rcu_sched(struct rcu_head *head, rcu_callback_t func);
> > > void synchronize_sched(void);
> > > @@ -838,45 +841,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> > > #define __is_kfree_rcu_offset(offset) ((offset) < 4096)
> > >
> > > /*
> > > - * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
> > > - */
> > > -#define __kfree_rcu(head, offset) \
> > > - do { \
> > > - BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
> > > - kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
> > > - } while (0)
> > > -
> > > -/**
> > > - * kfree_rcu() - kfree an object after a grace period.
> > > - * @ptr: pointer to kfree
> > > - * @rcu_head: the name of the struct rcu_head within the type of @ptr.
> > > - *
> > > - * Many rcu callbacks functions just call kfree() on the base structure.
> > > - * These functions are trivial, but their size adds up, and furthermore
> > > - * when they are used in a kernel module, that module must invoke the
> > > - * high-latency rcu_barrier() function at module-unload time.
> > > - *
> > > - * The kfree_rcu() function handles this issue. Rather than encoding a
> > > - * function address in the embedded rcu_head structure, kfree_rcu() instead
> > > - * encodes the offset of the rcu_head structure within the base structure.
> > > - * Because the functions are not allowed in the low-order 4096 bytes of
> > > - * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> > > - * If the offset is larger than 4095 bytes, a compile-time error will
> > > - * be generated in __kfree_rcu(). If this error is triggered, you can
> > > - * either fall back to use of call_rcu() or rearrange the structure to
> > > - * position the rcu_head structure into the first 4096 bytes.
> > > - *
> > > - * Note that the allowable offset might decrease in the future, for example,
> > > - * to allow something like kmem_cache_free_rcu().
> > > - *
> > > - * The BUILD_BUG_ON check must not involve any function calls, hence the
> > > - * checks are done in macros here.
> > > - */
> > > -#define kfree_rcu(ptr, rcu_head) \
> > > - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
> > > -
> > > -
> > > -/*
> > > * Place this after a lock-acquisition primitive to guarantee that
> > > * an UNLOCK+LOCK pair acts as a full barrier. This guarantee applies
> > > * if the UNLOCK and LOCK are executed by the same CPU or if the
> > > @@ -888,5 +852,4 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> > > #define smp_mb__after_unlock_lock() do { } while (0)
> > > #endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
> > >
> > > -
> > > #endif /* __LINUX_RCUPDATE_H */
> > > diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
> > > index 37d6fd3..7746b19 100644
> > > --- a/include/linux/rcutree.h
> > > +++ b/include/linux/rcutree.h
> > > @@ -48,8 +48,6 @@ void synchronize_rcu_bh(void);
> > > void synchronize_sched_expedited(void);
> > > void synchronize_rcu_expedited(void);
> > >
> > > -void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> > > -
> > > /**
> > > * synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period
> > > *
> > > diff --git a/include/linux/slab.h b/include/linux/slab.h
> > > index 50697a1..a71f6a78 100644
> > > --- a/include/linux/slab.h
> > > +++ b/include/linux/slab.h
> > > @@ -342,6 +342,50 @@ void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
> > > void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
> > > void kmem_cache_free(struct kmem_cache *, void *);
> > >
> > > +void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> > > +
> > > +/* Helper macro for kfree_rcu() to prevent argument-expansion eyestrain. */
> > > +#define __kfree_rcu(head, offset) \
> > > + do { \
> > > + unsigned long __o = (unsigned long)offset; \
> > > + BUILD_BUG_ON(!__is_kfree_rcu_offset(__o)); \
> > > + kfree_call_rcu(head, (rcu_callback_t)(__o)); \
> > > + } while (0)
> > > +
> > > +/**
> > > + * kfree_rcu() - kfree an object after a grace period.
> > > + * @ptr: pointer to kfree
> > > + * @rcu_head: the name of the struct rcu_head within the type of @ptr.
> >
> > So you already rename this parameter to 'rcu_head_name', and...
> >
> > > + *
> > > + * Many rcu callbacks functions just call kfree() on the base structure.
> > > + * These functions are trivial, but their size adds up, and furthermore
> > > + * when they are used in a kernel module, that module must invoke the
> > > + * high-latency rcu_barrier() function at module-unload time.
> > > + *
> > > + * The kfree_rcu() function handles this issue. Rather than encoding a
> > > + * function address in the embedded rcu_head structure, kfree_rcu() instead
> > > + * encodes the offset of the rcu_head structure within the base structure.
> > > + * Because the functions are not allowed in the low-order 4096 bytes of
> > > + * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> > > + * If the offset is larger than 4095 bytes, a compile-time error will
> > > + * be generated in __kfree_rcu(). If this error is triggered, you can
> > > + * either fall back to use of call_rcu() or rearrange the structure to
> > > + * position the rcu_head structure into the first 4096 bytes.
> > > + *
> > > + * Note that the allowable offset might decrease in the future, for example,
> > > + * to allow something like kmem_cache_free_rcu().
> > > + *
> > > + * The BUILD_BUG_ON check must not involve any function calls, hence the
> > > + * checks are done in macros here.
> > > + */
> > > +#define kfree_rcu(ptr, rcu_head_name) \
> > > + do { \
> > > + typeof(ptr) __ptr = ptr; \
> > > + unsigned long __off = offsetof(typeof(*(__ptr)), \
> > > + rcu_head_name); \
> > > + struct rcu_head *__rptr = (void *)__ptr + __off; \
> > > + __kfree_rcu(__rptr, __off); \
> > > + } while (0)
> >
> > why do you want to open code this?
>
> He needs it to be a macro so that offsetof() will work properly.
>
You lost me on this one, but it may be me who used the wrong phrase
"open code"..
So the kfree_rcu() used to be implemented as:
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
and Shoaib expanded as above, so I thought he must have a reason to do
this, maybe simply for the readability?
Regards,
Boqun
> > > /*
> > > * Bulk allocation and freeing operations. These are accelerated in an
> > > * allocator specific way to avoid taking locks repeatedly or building
> > > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > > index f9c0ca2..7d2830f 100644
> > > --- a/kernel/rcu/tree.c
> > > +++ b/kernel/rcu/tree.c
> > > @@ -3180,6 +3180,16 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
> > > }
> > > EXPORT_SYMBOL_GPL(call_rcu_sched);
> > >
> > > +/* Queue an RCU callback for lazy invocation after a grace period.
> > > + * Currently there is no way of tagging the lazy RCU callbacks in the
> > > + * list of pending callbacks. Until then, this function may only be
> > > + * called from kfree_call_rcu().
> > > + */
> > > +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func)
> > > +{
> > > + __call_rcu(head, func, &rcu_sched_state, -1, 1);
> >
> > Why do you switch this from rcu_state_p to rcu_sched_state? Have you
> > checked your changes don't break PREEMPT=y kernel? Did I miss something
> > subtle?
>
> Good catch, this would be a problem on PREEMPT=y kernels. I agree with
> Boqun's implicit suggestion of using rcu_state_p.
>
> Thanx, Paul
>
> > Regards,
> > Boqun
> >
> > > +}
> > > +
> > > /**
> > > * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
> > > * @head: structure to be used for queueing the RCU updates.
> > > @@ -3209,20 +3219,6 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
> > > EXPORT_SYMBOL_GPL(call_rcu_bh);
> > >
> > > /*
> > > - * Queue an RCU callback for lazy invocation after a grace period.
> > > - * This will likely be later named something like "call_rcu_lazy()",
> > > - * but this change will require some way of tagging the lazy RCU
> > > - * callbacks in the list of pending callbacks. Until then, this
> > > - * function may only be called from __kfree_rcu().
> > > - */
> > > -void kfree_call_rcu(struct rcu_head *head,
> > > - rcu_callback_t func)
> > > -{
> > > - __call_rcu(head, func, rcu_state_p, -1, 1);
> > > -}
> > > -EXPORT_SYMBOL_GPL(kfree_call_rcu);
> > > -
> > > -/*
> > > * Because a context switch is a grace period for RCU-sched and RCU-bh,
> > > * any blocking grace-period wait automatically implies a grace period
> > > * if there is only one CPU online at any point time during execution
> > > diff --git a/mm/slab_common.c b/mm/slab_common.c
> > > index c8cb367..0d8a63b 100644
> > > --- a/mm/slab_common.c
> > > +++ b/mm/slab_common.c
> > > @@ -1483,6 +1483,16 @@ void kzfree(const void *p)
> > > }
> > > EXPORT_SYMBOL(kzfree);
> > >
> > > +/*
> > > + * Queue Memory to be freed by RCU after a grace period.
> > > + */
> > > +void kfree_call_rcu(struct rcu_head *head,
> > > + rcu_callback_t func)
> > > +{
> > > + call_rcu_lazy(head, func);
> > > +}
> > > +EXPORT_SYMBOL_GPL(kfree_call_rcu);
> > > +
> > > /* Tracepoints definitions. */
> > > EXPORT_TRACEPOINT_SYMBOL(kmalloc);
> > > EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
> > > --
> > > 2.7.4
> > >
> > > --
> > > To unsubscribe, send a message with 'unsubscribe linux-mm' in
> > > the body to majordomo@kvack.org. For more info on Linux MM,
> > > see: http://www.linux-mm.org/ .
> > > Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
>
> >
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c
2017-12-22 2:38 ` Boqun Feng
@ 2017-12-22 2:53 ` Boqun Feng
2018-01-02 20:18 ` Paul E. McKenney
1 sibling, 0 replies; 6+ messages in thread
From: Boqun Feng @ 2017-12-22 2:53 UTC (permalink / raw)
To: Paul E. McKenney; +Cc: rao.shoaib, brouer, linux-mm
[-- Attachment #1: Type: text/plain, Size: 1250 bytes --]
On Fri, Dec 22, 2017 at 10:38:46AM +0800, Boqun Feng wrote:
> On Thu, Dec 21, 2017 at 05:42:12PM -0800, Paul E. McKenney wrote:
> > On Fri, Dec 22, 2017 at 09:17:04AM +0800, Boqun Feng wrote:
> > > Hi Shoaib,
> > >
> > > On Thu, Dec 21, 2017 at 02:32:50PM -0800, rao.shoaib@oracle.com wrote:
> > > > From: Rao Shoaib <rao.shoaib@oracle.com>
> > > >
> > > > This patch moves kfree_call_rcu() and related macros out of rcu code.
> > > > A new function call_rcu_lazy() is created for calling __call_rcu() with
> > > > the lazy flag. kfree_call_rcu() in the tiny implementation remains unchanged.
> > > >
> > >
> > > Mind to explain why you want to do this in the commit log?
> >
> > I am too close to this one, so I need you guys to hash this out. ;-)
> >
>
> I think simply improving the modularity is OK, but it's better to have
> some words in the commit log ;-)
>
Hmm.. seems like this is first part of the split version for:
https://lkml.kernel.org/r/1513705948-31072-1-git-send-email-rao.shoaib@oracle.com
In that case, Shoaib, I think you'd better send the whole thing as a
proper patchset(which is a set of patches) and write a cover letter.
Feel free to ask questions ;-)
Regards,
Boqun
[...]
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c
2017-12-22 2:38 ` Boqun Feng
2017-12-22 2:53 ` Boqun Feng
@ 2018-01-02 20:18 ` Paul E. McKenney
1 sibling, 0 replies; 6+ messages in thread
From: Paul E. McKenney @ 2018-01-02 20:18 UTC (permalink / raw)
To: Boqun Feng; +Cc: rao.shoaib, brouer, linux-mm
On Fri, Dec 22, 2017 at 10:38:46AM +0800, Boqun Feng wrote:
> On Thu, Dec 21, 2017 at 05:42:12PM -0800, Paul E. McKenney wrote:
> > On Fri, Dec 22, 2017 at 09:17:04AM +0800, Boqun Feng wrote:
> > > Hi Shoaib,
> > >
> > > On Thu, Dec 21, 2017 at 02:32:50PM -0800, rao.shoaib@oracle.com wrote:
> > > > From: Rao Shoaib <rao.shoaib@oracle.com>
> > > >
> > > > This patch moves kfree_call_rcu() and related macros out of rcu code.
> > > > A new function call_rcu_lazy() is created for calling __call_rcu() with
> > > > the lazy flag. kfree_call_rcu() in the tiny implementation remains unchanged.
> > > >
> > >
> > > Mind to explain why you want to do this in the commit log?
> >
> > I am too close to this one, so I need you guys to hash this out. ;-)
>
> I think simply improving the modularity is OK, but it's better to have
> some words in the commit log ;-)
Improved modularity is indeed the big benefit from my point of view.
> > > > V2: Addresses the noise generated by checkpatch
> > > >
> > > > Signed-off-by: Rao Shoaib <rao.shoaib@oracle.com>
> > > > ---
> > > > include/linux/rcupdate.h | 43 +++----------------------------------------
> > > > include/linux/rcutree.h | 2 --
> > > > include/linux/slab.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
> > > > kernel/rcu/tree.c | 24 ++++++++++--------------
> > > > mm/slab_common.c | 10 ++++++++++
> > > > 5 files changed, 67 insertions(+), 56 deletions(-)
> > > >
> > > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> > > > index a6ddc42..23ed728 100644
> > > > --- a/include/linux/rcupdate.h
> > > > +++ b/include/linux/rcupdate.h
> > > > @@ -55,6 +55,9 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
> > > > #define call_rcu call_rcu_sched
> > > > #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
> > > >
> > > > +/* only for use by kfree_call_rcu() */
> > > > +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func);
> > > > +
> > > > void call_rcu_bh(struct rcu_head *head, rcu_callback_t func);
> > > > void call_rcu_sched(struct rcu_head *head, rcu_callback_t func);
> > > > void synchronize_sched(void);
> > > > @@ -838,45 +841,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> > > > #define __is_kfree_rcu_offset(offset) ((offset) < 4096)
> > > >
> > > > /*
> > > > - * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
> > > > - */
> > > > -#define __kfree_rcu(head, offset) \
> > > > - do { \
> > > > - BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
> > > > - kfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \
> > > > - } while (0)
> > > > -
> > > > -/**
> > > > - * kfree_rcu() - kfree an object after a grace period.
> > > > - * @ptr: pointer to kfree
> > > > - * @rcu_head: the name of the struct rcu_head within the type of @ptr.
> > > > - *
> > > > - * Many rcu callbacks functions just call kfree() on the base structure.
> > > > - * These functions are trivial, but their size adds up, and furthermore
> > > > - * when they are used in a kernel module, that module must invoke the
> > > > - * high-latency rcu_barrier() function at module-unload time.
> > > > - *
> > > > - * The kfree_rcu() function handles this issue. Rather than encoding a
> > > > - * function address in the embedded rcu_head structure, kfree_rcu() instead
> > > > - * encodes the offset of the rcu_head structure within the base structure.
> > > > - * Because the functions are not allowed in the low-order 4096 bytes of
> > > > - * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> > > > - * If the offset is larger than 4095 bytes, a compile-time error will
> > > > - * be generated in __kfree_rcu(). If this error is triggered, you can
> > > > - * either fall back to use of call_rcu() or rearrange the structure to
> > > > - * position the rcu_head structure into the first 4096 bytes.
> > > > - *
> > > > - * Note that the allowable offset might decrease in the future, for example,
> > > > - * to allow something like kmem_cache_free_rcu().
> > > > - *
> > > > - * The BUILD_BUG_ON check must not involve any function calls, hence the
> > > > - * checks are done in macros here.
> > > > - */
> > > > -#define kfree_rcu(ptr, rcu_head) \
> > > > - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
> > > > -
> > > > -
> > > > -/*
> > > > * Place this after a lock-acquisition primitive to guarantee that
> > > > * an UNLOCK+LOCK pair acts as a full barrier. This guarantee applies
> > > > * if the UNLOCK and LOCK are executed by the same CPU or if the
> > > > @@ -888,5 +852,4 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> > > > #define smp_mb__after_unlock_lock() do { } while (0)
> > > > #endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
> > > >
> > > > -
> > > > #endif /* __LINUX_RCUPDATE_H */
> > > > diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
> > > > index 37d6fd3..7746b19 100644
> > > > --- a/include/linux/rcutree.h
> > > > +++ b/include/linux/rcutree.h
> > > > @@ -48,8 +48,6 @@ void synchronize_rcu_bh(void);
> > > > void synchronize_sched_expedited(void);
> > > > void synchronize_rcu_expedited(void);
> > > >
> > > > -void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> > > > -
> > > > /**
> > > > * synchronize_rcu_bh_expedited - Brute-force RCU-bh grace period
> > > > *
> > > > diff --git a/include/linux/slab.h b/include/linux/slab.h
> > > > index 50697a1..a71f6a78 100644
> > > > --- a/include/linux/slab.h
> > > > +++ b/include/linux/slab.h
> > > > @@ -342,6 +342,50 @@ void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment __malloc;
> > > > void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment __malloc;
> > > > void kmem_cache_free(struct kmem_cache *, void *);
> > > >
> > > > +void kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);
> > > > +
> > > > +/* Helper macro for kfree_rcu() to prevent argument-expansion eyestrain. */
> > > > +#define __kfree_rcu(head, offset) \
> > > > + do { \
> > > > + unsigned long __o = (unsigned long)offset; \
> > > > + BUILD_BUG_ON(!__is_kfree_rcu_offset(__o)); \
> > > > + kfree_call_rcu(head, (rcu_callback_t)(__o)); \
> > > > + } while (0)
> > > > +
> > > > +/**
> > > > + * kfree_rcu() - kfree an object after a grace period.
> > > > + * @ptr: pointer to kfree
> > > > + * @rcu_head: the name of the struct rcu_head within the type of @ptr.
> > >
> > > So you already rename this parameter to 'rcu_head_name', and...
> > >
> > > > + *
> > > > + * Many rcu callbacks functions just call kfree() on the base structure.
> > > > + * These functions are trivial, but their size adds up, and furthermore
> > > > + * when they are used in a kernel module, that module must invoke the
> > > > + * high-latency rcu_barrier() function at module-unload time.
> > > > + *
> > > > + * The kfree_rcu() function handles this issue. Rather than encoding a
> > > > + * function address in the embedded rcu_head structure, kfree_rcu() instead
> > > > + * encodes the offset of the rcu_head structure within the base structure.
> > > > + * Because the functions are not allowed in the low-order 4096 bytes of
> > > > + * kernel virtual memory, offsets up to 4095 bytes can be accommodated.
> > > > + * If the offset is larger than 4095 bytes, a compile-time error will
> > > > + * be generated in __kfree_rcu(). If this error is triggered, you can
> > > > + * either fall back to use of call_rcu() or rearrange the structure to
> > > > + * position the rcu_head structure into the first 4096 bytes.
> > > > + *
> > > > + * Note that the allowable offset might decrease in the future, for example,
> > > > + * to allow something like kmem_cache_free_rcu().
> > > > + *
> > > > + * The BUILD_BUG_ON check must not involve any function calls, hence the
> > > > + * checks are done in macros here.
> > > > + */
> > > > +#define kfree_rcu(ptr, rcu_head_name) \
> > > > + do { \
> > > > + typeof(ptr) __ptr = ptr; \
> > > > + unsigned long __off = offsetof(typeof(*(__ptr)), \
> > > > + rcu_head_name); \
> > > > + struct rcu_head *__rptr = (void *)__ptr + __off; \
> > > > + __kfree_rcu(__rptr, __off); \
> > > > + } while (0)
> > >
> > > why do you want to open code this?
> >
> > He needs it to be a macro so that offsetof() will work properly.
>
> You lost me on this one, but it may be me who used the wrong phrase
> "open code"..
>
> So the kfree_rcu() used to be implemented as:
>
> #define kfree_rcu(ptr, rcu_head) \
> __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
>
> and Shoaib expanded as above, so I thought he must have a reason to do
> this, maybe simply for the readability?
Ah, this was in response to feedback about not repeating macro parameters.
A bit over the top, perhaps, but the added typechecking alone is probably
well worth the added lines.
Thanx, Paul
> Regards,
> Boqun
>
> > > > /*
> > > > * Bulk allocation and freeing operations. These are accelerated in an
> > > > * allocator specific way to avoid taking locks repeatedly or building
> > > > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > > > index f9c0ca2..7d2830f 100644
> > > > --- a/kernel/rcu/tree.c
> > > > +++ b/kernel/rcu/tree.c
> > > > @@ -3180,6 +3180,16 @@ void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
> > > > }
> > > > EXPORT_SYMBOL_GPL(call_rcu_sched);
> > > >
> > > > +/* Queue an RCU callback for lazy invocation after a grace period.
> > > > + * Currently there is no way of tagging the lazy RCU callbacks in the
> > > > + * list of pending callbacks. Until then, this function may only be
> > > > + * called from kfree_call_rcu().
> > > > + */
> > > > +void call_rcu_lazy(struct rcu_head *head, rcu_callback_t func)
> > > > +{
> > > > + __call_rcu(head, func, &rcu_sched_state, -1, 1);
> > >
> > > Why do you switch this from rcu_state_p to rcu_sched_state? Have you
> > > checked your changes don't break PREEMPT=y kernel? Did I miss something
> > > subtle?
> >
> > Good catch, this would be a problem on PREEMPT=y kernels. I agree with
> > Boqun's implicit suggestion of using rcu_state_p.
> >
> > Thanx, Paul
> >
> > > Regards,
> > > Boqun
> > >
> > > > +}
> > > > +
> > > > /**
> > > > * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
> > > > * @head: structure to be used for queueing the RCU updates.
> > > > @@ -3209,20 +3219,6 @@ void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
> > > > EXPORT_SYMBOL_GPL(call_rcu_bh);
> > > >
> > > > /*
> > > > - * Queue an RCU callback for lazy invocation after a grace period.
> > > > - * This will likely be later named something like "call_rcu_lazy()",
> > > > - * but this change will require some way of tagging the lazy RCU
> > > > - * callbacks in the list of pending callbacks. Until then, this
> > > > - * function may only be called from __kfree_rcu().
> > > > - */
> > > > -void kfree_call_rcu(struct rcu_head *head,
> > > > - rcu_callback_t func)
> > > > -{
> > > > - __call_rcu(head, func, rcu_state_p, -1, 1);
> > > > -}
> > > > -EXPORT_SYMBOL_GPL(kfree_call_rcu);
> > > > -
> > > > -/*
> > > > * Because a context switch is a grace period for RCU-sched and RCU-bh,
> > > > * any blocking grace-period wait automatically implies a grace period
> > > > * if there is only one CPU online at any point time during execution
> > > > diff --git a/mm/slab_common.c b/mm/slab_common.c
> > > > index c8cb367..0d8a63b 100644
> > > > --- a/mm/slab_common.c
> > > > +++ b/mm/slab_common.c
> > > > @@ -1483,6 +1483,16 @@ void kzfree(const void *p)
> > > > }
> > > > EXPORT_SYMBOL(kzfree);
> > > >
> > > > +/*
> > > > + * Queue Memory to be freed by RCU after a grace period.
> > > > + */
> > > > +void kfree_call_rcu(struct rcu_head *head,
> > > > + rcu_callback_t func)
> > > > +{
> > > > + call_rcu_lazy(head, func);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(kfree_call_rcu);
> > > > +
> > > > /* Tracepoints definitions. */
> > > > EXPORT_TRACEPOINT_SYMBOL(kmalloc);
> > > > EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
> > > > --
> > > > 2.7.4
> > > >
> > > > --
> > > > To unsubscribe, send a message with 'unsubscribe linux-mm' in
> > > > the body to majordomo@kvack.org. For more info on Linux MM,
> > > > see: http://www.linux-mm.org/ .
> > > > Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
> >
> > >
> >
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-01-02 20:17 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-21 22:32 [PATCH v2 1/1] Move kfree_call_rcu() to slab_common.c rao.shoaib
2017-12-22 1:17 ` Boqun Feng
2017-12-22 1:42 ` Paul E. McKenney
2017-12-22 2:38 ` Boqun Feng
2017-12-22 2:53 ` Boqun Feng
2018-01-02 20:18 ` Paul E. McKenney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).