[RHEL7,COMMIT] kstat: Make global percpu kstat_pcpu_seq instead of percpu seq for every variable

Submitted by Konstantin Khorenko on Dec. 20, 2017, 9 a.m.

Details

Message ID 201712200900.vBK909il029770@finist_ce7.work
State New
Series "Make kstat_glob::swap_in percpu and cleanup"
Headers show

Commit Message

Konstantin Khorenko Dec. 20, 2017, 9 a.m.
The commit is pushed to "branch-rh7-3.10.0-693.11.1.vz7.39.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.11.1.vz7.39.8
------>
commit feb8aef1c8feaf0cd9481b2219984fb6026310ef
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Wed Dec 20 12:00:09 2017 +0300

    kstat: Make global percpu kstat_pcpu_seq instead of percpu seq for every variable
    
    It's unreasonable to create percpu seqlock for every kstat variable.
    As we update percpu value with irqs disable, concurrent update is
    not possible. So, we may create single percpu seqlock and use it
    for every kstat variable.
    
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 include/linux/vzstat.h  |  3 ++-
 kernel/sched/core.c     |  5 +++++
 kernel/ve/vzstat_core.c | 15 ++++++++++-----
 3 files changed, 17 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/linux/vzstat.h b/include/linux/vzstat.h
index 43a50f736887..fec88011b1d7 100644
--- a/include/linux/vzstat.h
+++ b/include/linux/vzstat.h
@@ -25,7 +25,6 @@  struct kstat_lat_snap_struct {
 struct kstat_lat_pcpu_snap_struct {
 	u64 maxlat, totlat;
 	unsigned long count;
-	seqcount_t lock;
 } ____cacheline_aligned_in_smp;
 
 struct kstat_lat_pcpu_struct {
@@ -84,6 +83,8 @@  struct kernel_stat_glob {
 	struct kstat_zone_avg zone_avg[MAX_NR_ZONES];
 } ____cacheline_aligned;
 
+DECLARE_PER_CPU(seqcount_t, kstat_pcpu_seq);
+
 extern struct kernel_stat_glob kstat_glob ____cacheline_aligned;
 extern spinlock_t kstat_glb_lock;
 
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 8418db07251d..75ef029b1595 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -141,6 +141,9 @@  DEFINE_SPINLOCK(kstat_glb_lock);
 EXPORT_SYMBOL(kstat_glob);
 EXPORT_SYMBOL(kstat_glb_lock);
 
+DEFINE_PER_CPU(seqcount_t, kstat_pcpu_seq);
+EXPORT_SYMBOL(kstat_pcpu_seq);
+
 static DEFINE_PER_CPU(struct kstat_lat_pcpu_snap_struct, glob_kstat_lat);
 static DEFINE_PER_CPU(struct kstat_lat_pcpu_snap_struct, glob_kstat_page_in);
 static DEFINE_PER_CPU(struct kstat_lat_pcpu_snap_struct, glob_kstat_swap_in);
@@ -157,6 +160,8 @@  void __init kstat_init(void)
 	int i;
 
 	seqcount_init(&kstat_glob.nr_unint_avg_seq);
+	for_each_possible_cpu(i)
+		seqcount_init(per_cpu_ptr(&kstat_pcpu_seq, i));
 	kstat_glob.sched_lat.cur = &glob_kstat_lat;
 	kstat_glob.page_in.cur = &glob_kstat_page_in;
 	kstat_glob.swap_in.cur = &glob_kstat_swap_in;
diff --git a/kernel/ve/vzstat_core.c b/kernel/ve/vzstat_core.c
index f048bcc0fe89..2501422d146b 100644
--- a/kernel/ve/vzstat_core.c
+++ b/kernel/ve/vzstat_core.c
@@ -46,14 +46,17 @@  void KSTAT_PERF_ADD(struct kstat_perf_pcpu_struct *ptr, u64 real_time, u64 cpu_t
 void KSTAT_LAT_PCPU_ADD(struct kstat_lat_pcpu_struct *p, u64 dur)
 {
 	struct kstat_lat_pcpu_snap_struct *cur;
+	seqcount_t *seq;
 
 	cur = this_cpu_ptr(p->cur);
-	write_seqcount_begin(&cur->lock);
+	seq = this_cpu_ptr(&kstat_pcpu_seq);
+
+	write_seqcount_begin(seq);
 	cur->count++;
 	if (cur->maxlat < dur)
 		cur->maxlat = dur;
 	cur->totlat += dur;
-	write_seqcount_end(&cur->lock);
+	write_seqcount_end(seq);
 }
 
 /*
@@ -62,17 +65,19 @@  void KSTAT_LAT_PCPU_ADD(struct kstat_lat_pcpu_struct *p, u64 dur)
  */
 void KSTAT_LAT_PCPU_UPDATE(struct kstat_lat_pcpu_struct *p)
 {
-	unsigned i, cpu;
 	struct kstat_lat_pcpu_snap_struct snap, *cur;
+	unsigned i, cpu;
+	seqcount_t *seq;
 	u64 m;
 
 	memset(&p->last, 0, sizeof(p->last));
 	for_each_online_cpu(cpu) {
 		cur = per_cpu_ptr(p->cur, cpu);
+		seq = per_cpu_ptr(&kstat_pcpu_seq, cpu);
 		do {
-			i = read_seqcount_begin(&cur->lock);
+			i = read_seqcount_begin(seq);
 			memcpy(&snap, cur, sizeof(snap));
-		} while (read_seqcount_retry(&cur->lock, i));
+		} while (read_seqcount_retry(seq, i));
 		/* 
 		 * read above and this update of maxlat is not atomic,
 		 * but this is OK, since it happens rarely and losing