History

Merge branch 'for-5.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup fix from Tejun Heo: "One commit to fix a possible A-A deadlock around u64_stats_sync on 32bit machines caused by updating it without disabling IRQ when it may be read from IRQ context" * 'for-5.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: rstat: fix A-A deadlock on 32bit around u64_stats_sync

Linus Torvalds committed 5 years ago

Commit 9a73fa32 parents 36a21d5 c3df5fb2 files · +19 −14Browse files

Unified · Split

2 files
  1. block/blk-cgroup.c +8 −6
  2. kernel/cgroup/rstat.c +11 −8
block/blk-cgroup.c+8−6
@@ -790,6 +790,7 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu) · 789 unmodified lines
790 struct blkcg_gq *parent = blkg->parent;790 struct blkcg_gq *parent = blkg->parent;
791 struct blkg_iostat_set *bisc = per_cpu_ptr(blkg->iostat_cpu, cpu);791 struct blkg_iostat_set *bisc = per_cpu_ptr(blkg->iostat_cpu, cpu);
792 struct blkg_iostat cur, delta;792 struct blkg_iostat cur, delta;
793 unsigned long flags;
793 unsigned int seq;794 unsigned int seq;
794 795
795 /* fetch the current per-cpu values */796 /* fetch the current per-cpu values */
@@ -799,21 +800,21 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu) · 3 unmodified lines
799 } while (u64_stats_fetch_retry(&bisc->sync, seq));800 } while (u64_stats_fetch_retry(&bisc->sync, seq));
800 801
801 /* propagate percpu delta to global */802 /* propagate percpu delta to global */
802 u64_stats_update_begin(&blkg->iostat.sync);803 flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
803 blkg_iostat_set(&delta, &cur);804 blkg_iostat_set(&delta, &cur);
804 blkg_iostat_sub(&delta, &bisc->last);805 blkg_iostat_sub(&delta, &bisc->last);
805 blkg_iostat_add(&blkg->iostat.cur, &delta);806 blkg_iostat_add(&blkg->iostat.cur, &delta);
806 blkg_iostat_add(&bisc->last, &delta);807 blkg_iostat_add(&bisc->last, &delta);
807 u64_stats_update_end(&blkg->iostat.sync);808 u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
808 809
809 /* propagate global delta to parent (unless that's root) */810 /* propagate global delta to parent (unless that's root) */
810 if (parent && parent->parent) {811 if (parent && parent->parent) {
811 u64_stats_update_begin(&parent->iostat.sync);812 flags = u64_stats_update_begin_irqsave(&parent->iostat.sync);
812 blkg_iostat_set(&delta, &blkg->iostat.cur);813 blkg_iostat_set(&delta, &blkg->iostat.cur);
813 blkg_iostat_sub(&delta, &blkg->iostat.last);814 blkg_iostat_sub(&delta, &blkg->iostat.last);
814 blkg_iostat_add(&parent->iostat.cur, &delta);815 blkg_iostat_add(&parent->iostat.cur, &delta);
815 blkg_iostat_add(&blkg->iostat.last, &delta);816 blkg_iostat_add(&blkg->iostat.last, &delta);
816 u64_stats_update_end(&parent->iostat.sync);817 u64_stats_update_end_irqrestore(&parent->iostat.sync, flags);
817 }818 }
818 }819 }
819 820
@@ -848,6 +849,7 @@ static void blkcg_fill_root_iostats(void) · 28 unmodified lines
848 memset(&tmp, 0, sizeof(tmp));849 memset(&tmp, 0, sizeof(tmp));
849 for_each_possible_cpu(cpu) {850 for_each_possible_cpu(cpu) {
850 struct disk_stats *cpu_dkstats;851 struct disk_stats *cpu_dkstats;
852 unsigned long flags;
851 853
852 cpu_dkstats = per_cpu_ptr(bdev->bd_stats, cpu);854 cpu_dkstats = per_cpu_ptr(bdev->bd_stats, cpu);
853 tmp.ios[BLKG_IOSTAT_READ] +=855 tmp.ios[BLKG_IOSTAT_READ] +=
@@ -864,9 +866,9 @@ static void blkcg_fill_root_iostats(void) · 10 unmodified lines
864 tmp.bytes[BLKG_IOSTAT_DISCARD] +=866 tmp.bytes[BLKG_IOSTAT_DISCARD] +=
865 cpu_dkstats->sectors[STAT_DISCARD] << 9;867 cpu_dkstats->sectors[STAT_DISCARD] << 9;
866 868
867 u64_stats_update_begin(&blkg->iostat.sync);869 flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
868 blkg_iostat_set(&blkg->iostat.cur, &tmp);870 blkg_iostat_set(&blkg->iostat.cur, &tmp);
869 u64_stats_update_end(&blkg->iostat.sync);871 u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
870 }872 }
871 }873 }
872}874}
kernel/cgroup/rstat.c+11−8
@@ -347,19 +347,20 @@ static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu) · 346 unmodified lines
347}347}
348 348
349static struct cgroup_rstat_cpu *349static struct cgroup_rstat_cpu *
350cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp)350cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp, unsigned long *flags)
351{351{
352 struct cgroup_rstat_cpu *rstatc;352 struct cgroup_rstat_cpu *rstatc;
353 353
354 rstatc = get_cpu_ptr(cgrp->rstat_cpu);354 rstatc = get_cpu_ptr(cgrp->rstat_cpu);
355 u64_stats_update_begin(&rstatc->bsync);355 *flags = u64_stats_update_begin_irqsave(&rstatc->bsync);
356 return rstatc;356 return rstatc;
357}357}
358 358
359static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp,359static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp,
360 struct cgroup_rstat_cpu *rstatc)360 struct cgroup_rstat_cpu *rstatc,
361 unsigned long flags)
361{362{
362 u64_stats_update_end(&rstatc->bsync);363 u64_stats_update_end_irqrestore(&rstatc->bsync, flags);
363 cgroup_rstat_updated(cgrp, smp_processor_id());364 cgroup_rstat_updated(cgrp, smp_processor_id());
364 put_cpu_ptr(rstatc);365 put_cpu_ptr(rstatc);
365}366}
@@ -367,18 +368,20 @@ static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp, · 1 unmodified line
367void __cgroup_account_cputime(struct cgroup *cgrp, u64 delta_exec)368void __cgroup_account_cputime(struct cgroup *cgrp, u64 delta_exec)
368{369{
369 struct cgroup_rstat_cpu *rstatc;370 struct cgroup_rstat_cpu *rstatc;
371 unsigned long flags;
370 372
371 rstatc = cgroup_base_stat_cputime_account_begin(cgrp);373 rstatc = cgroup_base_stat_cputime_account_begin(cgrp, &flags);
372 rstatc->bstat.cputime.sum_exec_runtime += delta_exec;374 rstatc->bstat.cputime.sum_exec_runtime += delta_exec;
373 cgroup_base_stat_cputime_account_end(cgrp, rstatc);375 cgroup_base_stat_cputime_account_end(cgrp, rstatc, flags);
374}376}
375 377
376void __cgroup_account_cputime_field(struct cgroup *cgrp,378void __cgroup_account_cputime_field(struct cgroup *cgrp,
377 enum cpu_usage_stat index, u64 delta_exec)379 enum cpu_usage_stat index, u64 delta_exec)
378{380{
379 struct cgroup_rstat_cpu *rstatc;381 struct cgroup_rstat_cpu *rstatc;
382 unsigned long flags;
380 383
381 rstatc = cgroup_base_stat_cputime_account_begin(cgrp);384 rstatc = cgroup_base_stat_cputime_account_begin(cgrp, &flags);
382 385
383 switch (index) {386 switch (index) {
384 case CPUTIME_USER:387 case CPUTIME_USER:
@@ -394,7 +397,7 @@ void __cgroup_account_cputime_field(struct cgroup *cgrp, · 9 unmodified lines
394 break;397 break;
395 }398 }
396 399
397 cgroup_base_stat_cputime_account_end(cgrp, rstatc);400 cgroup_base_stat_cputime_account_end(cgrp, rstatc, flags);
398}401}
399 402
400/*403/*

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t