Skip to content

Commit 6af89c6

Browse files
shakeelbhtejun
authored andcommitted
cgroup: remove per-cpu per-subsystem locks
The rstat update side used to insert the cgroup whose stats are updated in the update tree and the read side flush the update tree to get the latest uptodate stats. The per-cpu per-subsystem locks were used to synchronize the update and flush side. However now the update side does not access update tree but uses per-cpu lockless lists. So there is no need for locks to synchronize update and flush side. Let's remove them. Suggested-by: JP Kobryn <[email protected]> Signed-off-by: Shakeel Butt <[email protected]> Tested-by: JP Kobryn <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent 36df6e3 commit 6af89c6

File tree

3 files changed

+4
-150
lines changed

3 files changed

+4
-150
lines changed

include/linux/cgroup-defs.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,6 @@ struct css_rstat_cpu {
375375
* Child cgroups with stat updates on this cpu since the last read
376376
* are linked on the parent's ->updated_children through
377377
* ->updated_next. updated_children is terminated by its container css.
378-
*
379-
* In addition to being more compact, singly-linked list pointing to
380-
* the css makes it unnecessary for each per-cpu struct to point back
381-
* to the associated css.
382-
*
383-
* Protected by per-cpu css->ss->rstat_ss_cpu_lock.
384378
*/
385379
struct cgroup_subsys_state *updated_children;
386380
struct cgroup_subsys_state *updated_next; /* NULL if not on the list */
@@ -824,7 +818,6 @@ struct cgroup_subsys {
824818
unsigned int depends_on;
825819

826820
spinlock_t rstat_ss_lock;
827-
raw_spinlock_t __percpu *rstat_ss_cpu_lock;
828821
struct llist_head __percpu *lhead; /* lockless update list head */
829822
};
830823

include/trace/events/cgroup.h

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -257,53 +257,6 @@ DEFINE_EVENT(cgroup_rstat, cgroup_rstat_unlock,
257257
TP_ARGS(cgrp, cpu, contended)
258258
);
259259

260-
/*
261-
* Related to per CPU locks:
262-
* global rstat_base_cpu_lock for base stats
263-
* cgroup_subsys::rstat_ss_cpu_lock for subsystem stats
264-
*/
265-
DEFINE_EVENT(cgroup_rstat, cgroup_rstat_cpu_lock_contended,
266-
267-
TP_PROTO(struct cgroup *cgrp, int cpu, bool contended),
268-
269-
TP_ARGS(cgrp, cpu, contended)
270-
);
271-
272-
DEFINE_EVENT(cgroup_rstat, cgroup_rstat_cpu_lock_contended_fastpath,
273-
274-
TP_PROTO(struct cgroup *cgrp, int cpu, bool contended),
275-
276-
TP_ARGS(cgrp, cpu, contended)
277-
);
278-
279-
DEFINE_EVENT(cgroup_rstat, cgroup_rstat_cpu_locked,
280-
281-
TP_PROTO(struct cgroup *cgrp, int cpu, bool contended),
282-
283-
TP_ARGS(cgrp, cpu, contended)
284-
);
285-
286-
DEFINE_EVENT(cgroup_rstat, cgroup_rstat_cpu_locked_fastpath,
287-
288-
TP_PROTO(struct cgroup *cgrp, int cpu, bool contended),
289-
290-
TP_ARGS(cgrp, cpu, contended)
291-
);
292-
293-
DEFINE_EVENT(cgroup_rstat, cgroup_rstat_cpu_unlock,
294-
295-
TP_PROTO(struct cgroup *cgrp, int cpu, bool contended),
296-
297-
TP_ARGS(cgrp, cpu, contended)
298-
);
299-
300-
DEFINE_EVENT(cgroup_rstat, cgroup_rstat_cpu_unlock_fastpath,
301-
302-
TP_PROTO(struct cgroup *cgrp, int cpu, bool contended),
303-
304-
TP_ARGS(cgrp, cpu, contended)
305-
);
306-
307260
#endif /* _TRACE_CGROUP_H */
308261

309262
/* This part must be outside protection */

kernel/cgroup/rstat.c

Lines changed: 4 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <trace/events/cgroup.h>
1111

1212
static DEFINE_SPINLOCK(rstat_base_lock);
13-
static DEFINE_PER_CPU(raw_spinlock_t, rstat_base_cpu_lock);
1413
static DEFINE_PER_CPU(struct llist_head, rstat_backlog_list);
1514

1615
static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu);
@@ -53,74 +52,6 @@ static inline struct llist_head *ss_lhead_cpu(struct cgroup_subsys *ss, int cpu)
5352
return per_cpu_ptr(&rstat_backlog_list, cpu);
5453
}
5554

56-
static raw_spinlock_t *ss_rstat_cpu_lock(struct cgroup_subsys *ss, int cpu)
57-
{
58-
if (ss)
59-
return per_cpu_ptr(ss->rstat_ss_cpu_lock, cpu);
60-
61-
return per_cpu_ptr(&rstat_base_cpu_lock, cpu);
62-
}
63-
64-
/*
65-
* Helper functions for rstat per CPU locks.
66-
*
67-
* This makes it easier to diagnose locking issues and contention in
68-
* production environments. The parameter @fast_path determine the
69-
* tracepoints being added, allowing us to diagnose "flush" related
70-
* operations without handling high-frequency fast-path "update" events.
71-
*/
72-
static __always_inline
73-
unsigned long _css_rstat_cpu_lock(struct cgroup_subsys_state *css, int cpu,
74-
const bool fast_path)
75-
{
76-
struct cgroup *cgrp = css->cgroup;
77-
raw_spinlock_t *cpu_lock;
78-
unsigned long flags;
79-
bool contended;
80-
81-
/*
82-
* The _irqsave() is needed because the locks used for flushing are
83-
* spinlock_t which is a sleeping lock on PREEMPT_RT. Acquiring this lock
84-
* with the _irq() suffix only disables interrupts on a non-PREEMPT_RT
85-
* kernel. The raw_spinlock_t below disables interrupts on both
86-
* configurations. The _irqsave() ensures that interrupts are always
87-
* disabled and later restored.
88-
*/
89-
cpu_lock = ss_rstat_cpu_lock(css->ss, cpu);
90-
contended = !raw_spin_trylock_irqsave(cpu_lock, flags);
91-
if (contended) {
92-
if (fast_path)
93-
trace_cgroup_rstat_cpu_lock_contended_fastpath(cgrp, cpu, contended);
94-
else
95-
trace_cgroup_rstat_cpu_lock_contended(cgrp, cpu, contended);
96-
97-
raw_spin_lock_irqsave(cpu_lock, flags);
98-
}
99-
100-
if (fast_path)
101-
trace_cgroup_rstat_cpu_locked_fastpath(cgrp, cpu, contended);
102-
else
103-
trace_cgroup_rstat_cpu_locked(cgrp, cpu, contended);
104-
105-
return flags;
106-
}
107-
108-
static __always_inline
109-
void _css_rstat_cpu_unlock(struct cgroup_subsys_state *css, int cpu,
110-
unsigned long flags, const bool fast_path)
111-
{
112-
struct cgroup *cgrp = css->cgroup;
113-
raw_spinlock_t *cpu_lock;
114-
115-
if (fast_path)
116-
trace_cgroup_rstat_cpu_unlock_fastpath(cgrp, cpu, false);
117-
else
118-
trace_cgroup_rstat_cpu_unlock(cgrp, cpu, false);
119-
120-
cpu_lock = ss_rstat_cpu_lock(css->ss, cpu);
121-
raw_spin_unlock_irqrestore(cpu_lock, flags);
122-
}
123-
12455
/**
12556
* css_rstat_updated - keep track of updated rstat_cpu
12657
* @css: target cgroup subsystem state
@@ -323,15 +254,12 @@ static struct cgroup_subsys_state *css_rstat_updated_list(
323254
{
324255
struct css_rstat_cpu *rstatc = css_rstat_cpu(root, cpu);
325256
struct cgroup_subsys_state *head = NULL, *parent, *child;
326-
unsigned long flags;
327-
328-
flags = _css_rstat_cpu_lock(root, cpu, false);
329257

330258
css_process_update_tree(root->ss, cpu);
331259

332260
/* Return NULL if this subtree is not on-list */
333261
if (!rstatc->updated_next)
334-
goto unlock_ret;
262+
return NULL;
335263

336264
/*
337265
* Unlink @root from its parent. As the updated_children list is
@@ -363,8 +291,7 @@ static struct cgroup_subsys_state *css_rstat_updated_list(
363291
rstatc->updated_children = root;
364292
if (child != root)
365293
head = css_rstat_push_children(head, child, cpu);
366-
unlock_ret:
367-
_css_rstat_cpu_unlock(root, cpu, flags, false);
294+
368295
return head;
369296
}
370297

@@ -560,34 +487,15 @@ int __init ss_rstat_init(struct cgroup_subsys *ss)
560487
{
561488
int cpu;
562489

563-
#ifdef CONFIG_SMP
564-
/*
565-
* On uniprocessor machines, arch_spinlock_t is defined as an empty
566-
* struct. Avoid allocating a size of zero by having this block
567-
* excluded in this case. It's acceptable to leave the subsystem locks
568-
* unitialized since the associated lock functions are no-ops in the
569-
* non-smp case.
570-
*/
571-
if (ss) {
572-
ss->rstat_ss_cpu_lock = alloc_percpu(raw_spinlock_t);
573-
if (!ss->rstat_ss_cpu_lock)
574-
return -ENOMEM;
575-
}
576-
#endif
577-
578490
if (ss) {
579491
ss->lhead = alloc_percpu(struct llist_head);
580-
if (!ss->lhead) {
581-
free_percpu(ss->rstat_ss_cpu_lock);
492+
if (!ss->lhead)
582493
return -ENOMEM;
583-
}
584494
}
585495

586496
spin_lock_init(ss_rstat_lock(ss));
587-
for_each_possible_cpu(cpu) {
588-
raw_spin_lock_init(ss_rstat_cpu_lock(ss, cpu));
497+
for_each_possible_cpu(cpu)
589498
init_llist_head(ss_lhead_cpu(ss, cpu));
590-
}
591499

592500
return 0;
593501
}

0 commit comments

Comments
 (0)