Skip to content

Commit cfb2c10

Browse files
committed
Merge branches 'doc.2020.08.24a', 'fixes.2020.09.03b' and 'torture.2020.08.24a' into HEAD
doc.2020.08.24a: Documentation updates. fixes.2020.09.03b: Miscellaneous fixes. torture.2020.08.24a: Torture-test updates.
3 parents 7f45d6f + 70060b8 + b67a917 commit cfb2c10

File tree

24 files changed

+308
-191
lines changed

24 files changed

+308
-191
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4269,6 +4269,18 @@
42694269
are zero, rcutorture acts as if is interpreted
42704270
they are all non-zero.
42714271

4272+
rcutorture.irqreader= [KNL]
4273+
Run RCU readers from irq handlers, or, more
4274+
accurately, from a timer handler. Not all RCU
4275+
flavors take kindly to this sort of thing.
4276+
4277+
rcutorture.leakpointer= [KNL]
4278+
Leak an RCU-protected pointer out of the reader.
4279+
This can of course result in splats, and is
4280+
intended to test the ability of things like
4281+
CONFIG_RCU_STRICT_GRACE_PERIOD=y to detect
4282+
such leaks.
4283+
42724284
rcutorture.n_barrier_cbs= [KNL]
42734285
Set callbacks/threads for rcu_barrier() testing.
42744286

arch/x86/kvm/mmu/page_track.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
229229
return;
230230

231231
idx = srcu_read_lock(&head->track_srcu);
232-
hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
232+
hlist_for_each_entry_srcu(n, &head->track_notifier_list, node,
233+
srcu_read_lock_held(&head->track_srcu))
233234
if (n->track_write)
234235
n->track_write(vcpu, gpa, new, bytes, n);
235236
srcu_read_unlock(&head->track_srcu, idx);
@@ -254,7 +255,8 @@ void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
254255
return;
255256

256257
idx = srcu_read_lock(&head->track_srcu);
257-
hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
258+
hlist_for_each_entry_srcu(n, &head->track_notifier_list, node,
259+
srcu_read_lock_held(&head->track_srcu))
258260
if (n->track_flush_slot)
259261
n->track_flush_slot(kvm, slot, n);
260262
srcu_read_unlock(&head->track_srcu, idx);

include/linux/rculist.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,17 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
6363
RCU_LOCKDEP_WARN(!(cond) && !rcu_read_lock_any_held(), \
6464
"RCU-list traversed in non-reader section!"); \
6565
})
66+
67+
#define __list_check_srcu(cond) \
68+
({ \
69+
RCU_LOCKDEP_WARN(!(cond), \
70+
"RCU-list traversed without holding the required lock!");\
71+
})
6672
#else
6773
#define __list_check_rcu(dummy, cond, extra...) \
6874
({ check_arg_count_one(extra); })
75+
76+
#define __list_check_srcu(cond) ({ })
6977
#endif
7078

7179
/*
@@ -385,6 +393,25 @@ static inline void list_splice_tail_init_rcu(struct list_head *list,
385393
&pos->member != (head); \
386394
pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
387395

396+
/**
397+
* list_for_each_entry_srcu - iterate over rcu list of given type
398+
* @pos: the type * to use as a loop cursor.
399+
* @head: the head for your list.
400+
* @member: the name of the list_head within the struct.
401+
* @cond: lockdep expression for the lock required to traverse the list.
402+
*
403+
* This list-traversal primitive may safely run concurrently with
404+
* the _rcu list-mutation primitives such as list_add_rcu()
405+
* as long as the traversal is guarded by srcu_read_lock().
406+
* The lockdep expression srcu_read_lock_held() can be passed as the
407+
* cond argument from read side.
408+
*/
409+
#define list_for_each_entry_srcu(pos, head, member, cond) \
410+
for (__list_check_srcu(cond), \
411+
pos = list_entry_rcu((head)->next, typeof(*pos), member); \
412+
&pos->member != (head); \
413+
pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
414+
388415
/**
389416
* list_entry_lockless - get the struct for this entry
390417
* @ptr: the &struct list_head pointer.
@@ -683,6 +710,27 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n,
683710
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
684711
&(pos)->member)), typeof(*(pos)), member))
685712

713+
/**
714+
* hlist_for_each_entry_srcu - iterate over rcu list of given type
715+
* @pos: the type * to use as a loop cursor.
716+
* @head: the head for your list.
717+
* @member: the name of the hlist_node within the struct.
718+
* @cond: lockdep expression for the lock required to traverse the list.
719+
*
720+
* This list-traversal primitive may safely run concurrently with
721+
* the _rcu list-mutation primitives such as hlist_add_head_rcu()
722+
* as long as the traversal is guarded by srcu_read_lock().
723+
* The lockdep expression srcu_read_lock_held() can be passed as the
724+
* cond argument from read side.
725+
*/
726+
#define hlist_for_each_entry_srcu(pos, head, member, cond) \
727+
for (__list_check_srcu(cond), \
728+
pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\
729+
typeof(*(pos)), member); \
730+
pos; \
731+
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
732+
&(pos)->member)), typeof(*(pos)), member))
733+
686734
/**
687735
* hlist_for_each_entry_rcu_notrace - iterate over rcu list of given type (for tracing)
688736
* @pos: the type * to use as a loop cursor.

include/linux/rcupdate.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,8 @@ static inline void rcu_read_lock_bh(void)
709709
"rcu_read_lock_bh() used illegally while idle");
710710
}
711711

712-
/*
713-
* rcu_read_unlock_bh - marks the end of a softirq-only RCU critical section
712+
/**
713+
* rcu_read_unlock_bh() - marks the end of a softirq-only RCU critical section
714714
*
715715
* See rcu_read_lock_bh() for more information.
716716
*/
@@ -751,10 +751,10 @@ static inline notrace void rcu_read_lock_sched_notrace(void)
751751
__acquire(RCU_SCHED);
752752
}
753753

754-
/*
755-
* rcu_read_unlock_sched - marks the end of a RCU-classic critical section
754+
/**
755+
* rcu_read_unlock_sched() - marks the end of a RCU-classic critical section
756756
*
757-
* See rcu_read_lock_sched for more information.
757+
* See rcu_read_lock_sched() for more information.
758758
*/
759759
static inline void rcu_read_unlock_sched(void)
760760
{
@@ -945,7 +945,7 @@ static inline void rcu_head_init(struct rcu_head *rhp)
945945
}
946946

947947
/**
948-
* rcu_head_after_call_rcu - Has this rcu_head been passed to call_rcu()?
948+
* rcu_head_after_call_rcu() - Has this rcu_head been passed to call_rcu()?
949949
* @rhp: The rcu_head structure to test.
950950
* @f: The function passed to call_rcu() along with @rhp.
951951
*

include/linux/rcutiny.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ static inline void rcu_scheduler_starting(void) { }
103103
static inline void rcu_end_inkernel_boot(void) { }
104104
static inline bool rcu_inkernel_boot_has_ended(void) { return true; }
105105
static inline bool rcu_is_watching(void) { return true; }
106-
static inline bool __rcu_is_watching(void) { return true; }
107106
static inline void rcu_momentary_dyntick_idle(void) { }
108107
static inline void kfree_rcu_scheduler_running(void) { }
109108
static inline bool rcu_gp_might_be_stalled(void) { return false; }

include/linux/rcutree.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ extern int rcu_scheduler_active __read_mostly;
6464
void rcu_end_inkernel_boot(void);
6565
bool rcu_inkernel_boot_has_ended(void);
6666
bool rcu_is_watching(void);
67-
bool __rcu_is_watching(void);
6867
#ifndef CONFIG_PREEMPTION
6968
void rcu_all_qs(void);
7069
#endif

include/trace/events/rcu.h

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,17 @@ TRACE_EVENT_RCU(rcu_grace_period,
7474

7575
TP_STRUCT__entry(
7676
__field(const char *, rcuname)
77-
__field(unsigned long, gp_seq)
77+
__field(long, gp_seq)
7878
__field(const char *, gpevent)
7979
),
8080

8181
TP_fast_assign(
8282
__entry->rcuname = rcuname;
83-
__entry->gp_seq = gp_seq;
83+
__entry->gp_seq = (long)gp_seq;
8484
__entry->gpevent = gpevent;
8585
),
8686

87-
TP_printk("%s %lu %s",
87+
TP_printk("%s %ld %s",
8888
__entry->rcuname, __entry->gp_seq, __entry->gpevent)
8989
);
9090

@@ -114,8 +114,8 @@ TRACE_EVENT_RCU(rcu_future_grace_period,
114114

115115
TP_STRUCT__entry(
116116
__field(const char *, rcuname)
117-
__field(unsigned long, gp_seq)
118-
__field(unsigned long, gp_seq_req)
117+
__field(long, gp_seq)
118+
__field(long, gp_seq_req)
119119
__field(u8, level)
120120
__field(int, grplo)
121121
__field(int, grphi)
@@ -124,16 +124,16 @@ TRACE_EVENT_RCU(rcu_future_grace_period,
124124

125125
TP_fast_assign(
126126
__entry->rcuname = rcuname;
127-
__entry->gp_seq = gp_seq;
128-
__entry->gp_seq_req = gp_seq_req;
127+
__entry->gp_seq = (long)gp_seq;
128+
__entry->gp_seq_req = (long)gp_seq_req;
129129
__entry->level = level;
130130
__entry->grplo = grplo;
131131
__entry->grphi = grphi;
132132
__entry->gpevent = gpevent;
133133
),
134134

135-
TP_printk("%s %lu %lu %u %d %d %s",
136-
__entry->rcuname, __entry->gp_seq, __entry->gp_seq_req, __entry->level,
135+
TP_printk("%s %ld %ld %u %d %d %s",
136+
__entry->rcuname, (long)__entry->gp_seq, (long)__entry->gp_seq_req, __entry->level,
137137
__entry->grplo, __entry->grphi, __entry->gpevent)
138138
);
139139

@@ -153,7 +153,7 @@ TRACE_EVENT_RCU(rcu_grace_period_init,
153153

154154
TP_STRUCT__entry(
155155
__field(const char *, rcuname)
156-
__field(unsigned long, gp_seq)
156+
__field(long, gp_seq)
157157
__field(u8, level)
158158
__field(int, grplo)
159159
__field(int, grphi)
@@ -162,14 +162,14 @@ TRACE_EVENT_RCU(rcu_grace_period_init,
162162

163163
TP_fast_assign(
164164
__entry->rcuname = rcuname;
165-
__entry->gp_seq = gp_seq;
165+
__entry->gp_seq = (long)gp_seq;
166166
__entry->level = level;
167167
__entry->grplo = grplo;
168168
__entry->grphi = grphi;
169169
__entry->qsmask = qsmask;
170170
),
171171

172-
TP_printk("%s %lu %u %d %d %lx",
172+
TP_printk("%s %ld %u %d %d %lx",
173173
__entry->rcuname, __entry->gp_seq, __entry->level,
174174
__entry->grplo, __entry->grphi, __entry->qsmask)
175175
);
@@ -197,17 +197,17 @@ TRACE_EVENT_RCU(rcu_exp_grace_period,
197197

198198
TP_STRUCT__entry(
199199
__field(const char *, rcuname)
200-
__field(unsigned long, gpseq)
200+
__field(long, gpseq)
201201
__field(const char *, gpevent)
202202
),
203203

204204
TP_fast_assign(
205205
__entry->rcuname = rcuname;
206-
__entry->gpseq = gpseq;
206+
__entry->gpseq = (long)gpseq;
207207
__entry->gpevent = gpevent;
208208
),
209209

210-
TP_printk("%s %lu %s",
210+
TP_printk("%s %ld %s",
211211
__entry->rcuname, __entry->gpseq, __entry->gpevent)
212212
);
213213

@@ -316,17 +316,17 @@ TRACE_EVENT_RCU(rcu_preempt_task,
316316

317317
TP_STRUCT__entry(
318318
__field(const char *, rcuname)
319-
__field(unsigned long, gp_seq)
319+
__field(long, gp_seq)
320320
__field(int, pid)
321321
),
322322

323323
TP_fast_assign(
324324
__entry->rcuname = rcuname;
325-
__entry->gp_seq = gp_seq;
325+
__entry->gp_seq = (long)gp_seq;
326326
__entry->pid = pid;
327327
),
328328

329-
TP_printk("%s %lu %d",
329+
TP_printk("%s %ld %d",
330330
__entry->rcuname, __entry->gp_seq, __entry->pid)
331331
);
332332

@@ -343,17 +343,17 @@ TRACE_EVENT_RCU(rcu_unlock_preempted_task,
343343

344344
TP_STRUCT__entry(
345345
__field(const char *, rcuname)
346-
__field(unsigned long, gp_seq)
346+
__field(long, gp_seq)
347347
__field(int, pid)
348348
),
349349

350350
TP_fast_assign(
351351
__entry->rcuname = rcuname;
352-
__entry->gp_seq = gp_seq;
352+
__entry->gp_seq = (long)gp_seq;
353353
__entry->pid = pid;
354354
),
355355

356-
TP_printk("%s %lu %d", __entry->rcuname, __entry->gp_seq, __entry->pid)
356+
TP_printk("%s %ld %d", __entry->rcuname, __entry->gp_seq, __entry->pid)
357357
);
358358

359359
/*
@@ -374,7 +374,7 @@ TRACE_EVENT_RCU(rcu_quiescent_state_report,
374374

375375
TP_STRUCT__entry(
376376
__field(const char *, rcuname)
377-
__field(unsigned long, gp_seq)
377+
__field(long, gp_seq)
378378
__field(unsigned long, mask)
379379
__field(unsigned long, qsmask)
380380
__field(u8, level)
@@ -385,7 +385,7 @@ TRACE_EVENT_RCU(rcu_quiescent_state_report,
385385

386386
TP_fast_assign(
387387
__entry->rcuname = rcuname;
388-
__entry->gp_seq = gp_seq;
388+
__entry->gp_seq = (long)gp_seq;
389389
__entry->mask = mask;
390390
__entry->qsmask = qsmask;
391391
__entry->level = level;
@@ -394,7 +394,7 @@ TRACE_EVENT_RCU(rcu_quiescent_state_report,
394394
__entry->gp_tasks = gp_tasks;
395395
),
396396

397-
TP_printk("%s %lu %lx>%lx %u %d %d %u",
397+
TP_printk("%s %ld %lx>%lx %u %d %d %u",
398398
__entry->rcuname, __entry->gp_seq,
399399
__entry->mask, __entry->qsmask, __entry->level,
400400
__entry->grplo, __entry->grphi, __entry->gp_tasks)
@@ -415,19 +415,19 @@ TRACE_EVENT_RCU(rcu_fqs,
415415

416416
TP_STRUCT__entry(
417417
__field(const char *, rcuname)
418-
__field(unsigned long, gp_seq)
418+
__field(long, gp_seq)
419419
__field(int, cpu)
420420
__field(const char *, qsevent)
421421
),
422422

423423
TP_fast_assign(
424424
__entry->rcuname = rcuname;
425-
__entry->gp_seq = gp_seq;
425+
__entry->gp_seq = (long)gp_seq;
426426
__entry->cpu = cpu;
427427
__entry->qsevent = qsevent;
428428
),
429429

430-
TP_printk("%s %lu %d %s",
430+
TP_printk("%s %ld %d %s",
431431
__entry->rcuname, __entry->gp_seq,
432432
__entry->cpu, __entry->qsevent)
433433
);

kernel/entry/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
278278
* terminate a grace period, if and only if the timer interrupt is
279279
* not nested into another interrupt.
280280
*
281-
* Checking for __rcu_is_watching() here would prevent the nesting
281+
* Checking for rcu_is_watching() here would prevent the nesting
282282
* interrupt to invoke rcu_irq_enter(). If that nested interrupt is
283283
* the tick then rcu_flavor_sched_clock_irq() would wrongfully
284284
* assume that it is the first interupt and eventually claim

kernel/locking/locktorture.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ static struct lock_torture_ops rwsem_lock_ops = {
566566
#include <linux/percpu-rwsem.h>
567567
static struct percpu_rw_semaphore pcpu_rwsem;
568568

569-
void torture_percpu_rwsem_init(void)
569+
static void torture_percpu_rwsem_init(void)
570570
{
571571
BUG_ON(percpu_init_rwsem(&pcpu_rwsem));
572572
}

kernel/rcu/rcu_segcblist.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,16 @@ bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq)
475475
* Also advance to the oldest segment of callbacks whose
476476
* ->gp_seq[] completion is at or after that passed in via "seq",
477477
* skipping any empty segments.
478+
*
479+
* Note that segment "i" (and any lower-numbered segments
480+
* containing older callbacks) will be unaffected, and their
481+
* grace-period numbers remain unchanged. For example, if i ==
482+
* WAIT_TAIL, then neither WAIT_TAIL nor DONE_TAIL will be touched.
483+
* Instead, the CBs in NEXT_TAIL will be merged with those in
484+
* NEXT_READY_TAIL and the grace-period number of NEXT_READY_TAIL
485+
* would be updated. NEXT_TAIL would then be empty.
478486
*/
479-
if (++i >= RCU_NEXT_TAIL)
487+
if (rcu_segcblist_restempty(rsclp, i) || ++i >= RCU_NEXT_TAIL)
480488
return false;
481489

482490
/*

0 commit comments

Comments
 (0)