Skip to content

Commit dea2d92

Browse files
committed
Merge branch 'slab/for-6.15/kfree_rcu_tiny' into slab/for-next
Merge the slab feature branch kfree_rcu_tiny for 6.15: - Move the TINY_RCU kvfree_rcu() implementation from RCU to SLAB subsystem and cleanup its integration.
2 parents 747e2cf + c9f8f12 commit dea2d92

File tree

11 files changed

+113
-126
lines changed

11 files changed

+113
-126
lines changed

include/linux/rcupdate.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,12 +1025,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
10251025
#define RCU_POINTER_INITIALIZER(p, v) \
10261026
.p = RCU_INITIALIZER(v)
10271027

1028-
/*
1029-
* Does the specified offset indicate that the corresponding rcu_head
1030-
* structure can be handled by kvfree_rcu()?
1031-
*/
1032-
#define __is_kvfree_rcu_offset(offset) ((offset) < 4096)
1033-
10341028
/**
10351029
* kfree_rcu() - kfree an object after a grace period.
10361030
* @ptr: pointer to kfree for double-argument invocations.
@@ -1041,11 +1035,11 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
10411035
* when they are used in a kernel module, that module must invoke the
10421036
* high-latency rcu_barrier() function at module-unload time.
10431037
*
1044-
* The kfree_rcu() function handles this issue. Rather than encoding a
1045-
* function address in the embedded rcu_head structure, kfree_rcu() instead
1046-
* encodes the offset of the rcu_head structure within the base structure.
1047-
* Because the functions are not allowed in the low-order 4096 bytes of
1048-
* kernel virtual memory, offsets up to 4095 bytes can be accommodated.
1038+
* The kfree_rcu() function handles this issue. In order to have a universal
1039+
* callback function handling different offsets of rcu_head, the callback needs
1040+
* to determine the starting address of the freed object, which can be a large
1041+
* kmalloc or vmalloc allocation. To allow simply aligning the pointer down to
1042+
* page boundary for those, only offsets up to 4095 bytes can be accommodated.
10491043
* If the offset is larger than 4095 bytes, a compile-time error will
10501044
* be generated in kvfree_rcu_arg_2(). If this error is triggered, you can
10511045
* either fall back to use of call_rcu() or rearrange the structure to
@@ -1082,14 +1076,23 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
10821076
#define kfree_rcu_mightsleep(ptr) kvfree_rcu_arg_1(ptr)
10831077
#define kvfree_rcu_mightsleep(ptr) kvfree_rcu_arg_1(ptr)
10841078

1079+
/*
1080+
* In mm/slab_common.c, no suitable header to include here.
1081+
*/
1082+
void kvfree_call_rcu(struct rcu_head *head, void *ptr);
1083+
1084+
/*
1085+
* The BUILD_BUG_ON() makes sure the rcu_head offset can be handled. See the
1086+
* comment of kfree_rcu() for details.
1087+
*/
10851088
#define kvfree_rcu_arg_2(ptr, rhf) \
10861089
do { \
10871090
typeof (ptr) ___p = (ptr); \
10881091
\
1089-
if (___p) { \
1090-
BUILD_BUG_ON(!__is_kvfree_rcu_offset(offsetof(typeof(*(ptr)), rhf))); \
1091-
kvfree_call_rcu(&((___p)->rhf), (void *) (___p)); \
1092-
} \
1092+
if (___p) { \
1093+
BUILD_BUG_ON(offsetof(typeof(*(ptr)), rhf) >= 4096); \
1094+
kvfree_call_rcu(&((___p)->rhf), (void *) (___p)); \
1095+
} \
10931096
} while (0)
10941097

10951098
#define kvfree_rcu_arg_1(ptr) \

include/linux/rcutiny.h

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -90,41 +90,6 @@ static inline void synchronize_rcu_expedited(void)
9090
synchronize_rcu();
9191
}
9292

93-
/*
94-
* Add one more declaration of kvfree() here. It is
95-
* not so straight forward to just include <linux/mm.h>
96-
* where it is defined due to getting many compile
97-
* errors caused by that include.
98-
*/
99-
extern void kvfree(const void *addr);
100-
101-
static inline void __kvfree_call_rcu(struct rcu_head *head, void *ptr)
102-
{
103-
if (head) {
104-
call_rcu(head, (rcu_callback_t) ((void *) head - ptr));
105-
return;
106-
}
107-
108-
// kvfree_rcu(one_arg) call.
109-
might_sleep();
110-
synchronize_rcu();
111-
kvfree(ptr);
112-
}
113-
114-
static inline void kvfree_rcu_barrier(void)
115-
{
116-
rcu_barrier();
117-
}
118-
119-
#ifdef CONFIG_KASAN_GENERIC
120-
void kvfree_call_rcu(struct rcu_head *head, void *ptr);
121-
#else
122-
static inline void kvfree_call_rcu(struct rcu_head *head, void *ptr)
123-
{
124-
__kvfree_call_rcu(head, ptr);
125-
}
126-
#endif
127-
12893
void rcu_qs(void);
12994

13095
static inline void rcu_softirq_qs(void)
@@ -164,7 +129,6 @@ static inline void rcu_end_inkernel_boot(void) { }
164129
static inline bool rcu_inkernel_boot_has_ended(void) { return true; }
165130
static inline bool rcu_is_watching(void) { return true; }
166131
static inline void rcu_momentary_eqs(void) { }
167-
static inline void kfree_rcu_scheduler_running(void) { }
168132

169133
/* Avoid RCU read-side critical sections leaking across. */
170134
static inline void rcu_all_qs(void) { barrier(); }

include/linux/rcutree.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,9 @@ static inline void rcu_virt_note_context_switch(void)
3434
}
3535

3636
void synchronize_rcu_expedited(void);
37-
void kvfree_call_rcu(struct rcu_head *head, void *ptr);
38-
void kvfree_rcu_barrier(void);
3937

4038
void rcu_barrier(void);
4139
void rcu_momentary_eqs(void);
42-
void kfree_rcu_scheduler_running(void);
4340

4441
struct rcu_gp_oldstate {
4542
unsigned long rgos_norm;

include/linux/slab.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/gfp.h>
1717
#include <linux/overflow.h>
1818
#include <linux/types.h>
19+
#include <linux/rcupdate.h>
1920
#include <linux/workqueue.h>
2021
#include <linux/percpu-refcount.h>
2122
#include <linux/cleanup.h>
@@ -1080,6 +1081,19 @@ extern void kvfree_sensitive(const void *addr, size_t len);
10801081

10811082
unsigned int kmem_cache_size(struct kmem_cache *s);
10821083

1084+
#ifndef CONFIG_KVFREE_RCU_BATCHED
1085+
static inline void kvfree_rcu_barrier(void)
1086+
{
1087+
rcu_barrier();
1088+
}
1089+
1090+
static inline void kfree_rcu_scheduler_running(void) { }
1091+
#else
1092+
void kvfree_rcu_barrier(void);
1093+
1094+
void kfree_rcu_scheduler_running(void);
1095+
#endif
1096+
10831097
/**
10841098
* kmalloc_size_roundup - Report allocation bucket size for the given size
10851099
*

include/trace/events/rcu.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -560,40 +560,6 @@ TRACE_EVENT_RCU(rcu_segcb_stats,
560560

561561
);
562562

563-
/*
564-
* Tracepoint for the registration of a single RCU callback of the special
565-
* kvfree() form. The first argument is the RCU type, the second argument
566-
* is a pointer to the RCU callback, the third argument is the offset
567-
* of the callback within the enclosing RCU-protected data structure,
568-
* the fourth argument is the number of lazy callbacks queued, and the
569-
* fifth argument is the total number of callbacks queued.
570-
*/
571-
TRACE_EVENT_RCU(rcu_kvfree_callback,
572-
573-
TP_PROTO(const char *rcuname, struct rcu_head *rhp, unsigned long offset,
574-
long qlen),
575-
576-
TP_ARGS(rcuname, rhp, offset, qlen),
577-
578-
TP_STRUCT__entry(
579-
__field(const char *, rcuname)
580-
__field(void *, rhp)
581-
__field(unsigned long, offset)
582-
__field(long, qlen)
583-
),
584-
585-
TP_fast_assign(
586-
__entry->rcuname = rcuname;
587-
__entry->rhp = rhp;
588-
__entry->offset = offset;
589-
__entry->qlen = qlen;
590-
),
591-
592-
TP_printk("%s rhp=%p func=%ld %ld",
593-
__entry->rcuname, __entry->rhp, __entry->offset,
594-
__entry->qlen)
595-
);
596-
597563
/*
598564
* Tracepoint for marking the beginning rcu_do_batch, performed to start
599565
* RCU callback invocation. The first argument is the RCU flavor,

kernel/rcu/tiny.c

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,8 @@ void rcu_sched_clock_irq(int user)
8585
static inline bool rcu_reclaim_tiny(struct rcu_head *head)
8686
{
8787
rcu_callback_t f;
88-
unsigned long offset = (unsigned long)head->func;
8988

9089
rcu_lock_acquire(&rcu_callback_map);
91-
if (__is_kvfree_rcu_offset(offset)) {
92-
trace_rcu_invoke_kvfree_callback("", head, offset);
93-
kvfree((void *)head - offset);
94-
rcu_lock_release(&rcu_callback_map);
95-
return true;
96-
}
9790

9891
trace_rcu_invoke_callback("", head);
9992
f = head->func;
@@ -159,10 +152,6 @@ void synchronize_rcu(void)
159152
}
160153
EXPORT_SYMBOL_GPL(synchronize_rcu);
161154

162-
static void tiny_rcu_leak_callback(struct rcu_head *rhp)
163-
{
164-
}
165-
166155
/*
167156
* Post an RCU callback to be invoked after the end of an RCU grace
168157
* period. But since we have but one CPU, that would be after any
@@ -178,9 +167,6 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func)
178167
pr_err("%s(): Double-freed CB %p->%pS()!!! ", __func__, head, head->func);
179168
mem_dump_obj(head);
180169
}
181-
182-
if (!__is_kvfree_rcu_offset((unsigned long)head->func))
183-
WRITE_ONCE(head->func, tiny_rcu_leak_callback);
184170
return;
185171
}
186172

@@ -246,17 +232,6 @@ bool poll_state_synchronize_rcu(unsigned long oldstate)
246232
}
247233
EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
248234

249-
#ifdef CONFIG_KASAN_GENERIC
250-
void kvfree_call_rcu(struct rcu_head *head, void *ptr)
251-
{
252-
if (head)
253-
kasan_record_aux_stack(ptr);
254-
255-
__kvfree_call_rcu(head, ptr);
256-
}
257-
EXPORT_SYMBOL_GPL(kvfree_call_rcu);
258-
#endif
259-
260235
void __init rcu_init(void)
261236
{
262237
open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);

kernel/rcu/tree.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2931,13 +2931,8 @@ static int __init rcu_spawn_core_kthreads(void)
29312931
static void rcutree_enqueue(struct rcu_data *rdp, struct rcu_head *head, rcu_callback_t func)
29322932
{
29332933
rcu_segcblist_enqueue(&rdp->cblist, head);
2934-
if (__is_kvfree_rcu_offset((unsigned long)func))
2935-
trace_rcu_kvfree_callback(rcu_state.name, head,
2936-
(unsigned long)func,
2937-
rcu_segcblist_n_cbs(&rdp->cblist));
2938-
else
2939-
trace_rcu_callback(rcu_state.name, head,
2940-
rcu_segcblist_n_cbs(&rdp->cblist));
2934+
trace_rcu_callback(rcu_state.name, head,
2935+
rcu_segcblist_n_cbs(&rdp->cblist));
29412936
trace_rcu_segcb_stats(&rdp->cblist, TPS("SegCBQueued"));
29422937
}
29432938

mm/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ menu "Slab allocator options"
242242
config SLUB
243243
def_bool y
244244

245+
config KVFREE_RCU_BATCHED
246+
def_bool y
247+
depends on !SLUB_TINY && !TINY_RCU
248+
245249
config SLUB_TINY
246250
bool "Configure for minimal memory footprint"
247251
depends on EXPERT

mm/slab.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ void __memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
582582
void **p, int objects, struct slabobj_ext *obj_exts);
583583
#endif
584584

585+
void kvfree_rcu_cb(struct rcu_head *head);
586+
585587
size_t __ksize(const void *objp);
586588

587589
static inline size_t slab_ksize(const struct kmem_cache *s)

mm/slab_common.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,29 @@ EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
12771277
EXPORT_TRACEPOINT_SYMBOL(kfree);
12781278
EXPORT_TRACEPOINT_SYMBOL(kmem_cache_free);
12791279

1280+
#ifndef CONFIG_KVFREE_RCU_BATCHED
1281+
1282+
void kvfree_call_rcu(struct rcu_head *head, void *ptr)
1283+
{
1284+
if (head) {
1285+
kasan_record_aux_stack(ptr);
1286+
call_rcu(head, kvfree_rcu_cb);
1287+
return;
1288+
}
1289+
1290+
// kvfree_rcu(one_arg) call.
1291+
might_sleep();
1292+
synchronize_rcu();
1293+
kvfree(ptr);
1294+
}
1295+
EXPORT_SYMBOL_GPL(kvfree_call_rcu);
1296+
1297+
void __init kvfree_rcu_init(void)
1298+
{
1299+
}
1300+
1301+
#else /* CONFIG_KVFREE_RCU_BATCHED */
1302+
12801303
/*
12811304
* This rcu parameter is runtime-read-only. It reflects
12821305
* a minimum allowed number of objects which can be cached
@@ -1527,8 +1550,7 @@ kvfree_rcu_list(struct rcu_head *head)
15271550
rcu_lock_acquire(&rcu_callback_map);
15281551
trace_rcu_invoke_kvfree_callback("slab", head, offset);
15291552

1530-
if (!WARN_ON_ONCE(!__is_kvfree_rcu_offset(offset)))
1531-
kvfree(ptr);
1553+
kvfree(ptr);
15321554

15331555
rcu_lock_release(&rcu_callback_map);
15341556
cond_resched_tasks_rcu_qs();
@@ -1856,8 +1878,6 @@ add_ptr_to_bulk_krc_lock(struct kfree_rcu_cpu **krcp,
18561878
return true;
18571879
}
18581880

1859-
#if !defined(CONFIG_TINY_RCU)
1860-
18611881
static enum hrtimer_restart
18621882
schedule_page_work_fn(struct hrtimer *t)
18631883
{
@@ -2066,8 +2086,6 @@ void kvfree_rcu_barrier(void)
20662086
}
20672087
EXPORT_SYMBOL_GPL(kvfree_rcu_barrier);
20682088

2069-
#endif /* #if !defined(CONFIG_TINY_RCU) */
2070-
20712089
static unsigned long
20722090
kfree_rcu_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
20732091
{
@@ -2161,3 +2179,6 @@ void __init kvfree_rcu_init(void)
21612179

21622180
shrinker_register(kfree_rcu_shrinker);
21632181
}
2182+
2183+
#endif /* CONFIG_KVFREE_RCU_BATCHED */
2184+

0 commit comments

Comments
 (0)