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
Showing the changes to kernel (1 of 2 files). Show all
Unified · Split
| @@ -347,19 +347,20 @@ static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu) · 346 unmodified lines | |||
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static struct cgroup_rstat_cpu * | 349 | static struct cgroup_rstat_cpu * |
| 350 | cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp) | 350 | cgroup_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 | ||
| 359 | static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp, | 359 | static 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 | |||
| 367 | void __cgroup_account_cputime(struct cgroup *cgrp, u64 delta_exec) | 368 | void __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 | ||
| 376 | void __cgroup_account_cputime_field(struct cgroup *cgrp, | 378 | void __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 | /* |