Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vmstat: get rid of the ugly cpu_stat_off variable

The cpu_stat_off variable is unecessary since we can check if a
workqueue request is pending otherwise. Removal of cpu_stat_off makes
it pretty easy for the vmstat shepherd to ensure that the proper things
happen.

Removing the state also removes all races related to it. Should a
workqueue not be scheduled as needed for vmstat_update then the shepherd
will notice and schedule it as needed. Should a workqueue be
unecessarily scheduled then the vmstat updater will disable it.

[akpm@linux-foundation.org: fix indentation, per Michal]
Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1605061306460.17934@east.gentwo.org
Signed-off-by: Christoph Lameter <cl@linux.com>
Cc: Tejun Heo <htejun@gmail.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Christoph Lameter and committed by
Linus Torvalds
7b8da4c7 51038171

+10 -41
+10 -41
mm/vmstat.c
··· 1352 1352 static struct workqueue_struct *vmstat_wq; 1353 1353 static DEFINE_PER_CPU(struct delayed_work, vmstat_work); 1354 1354 int sysctl_stat_interval __read_mostly = HZ; 1355 - static cpumask_var_t cpu_stat_off; 1356 1355 1357 1356 #ifdef CONFIG_PROC_FS 1358 1357 static void refresh_vm_stats(struct work_struct *work) ··· 1420 1421 * Counters were updated so we expect more updates 1421 1422 * to occur in the future. Keep on running the 1422 1423 * update worker thread. 1423 - * If we were marked on cpu_stat_off clear the flag 1424 - * so that vmstat_shepherd doesn't schedule us again. 1425 1424 */ 1426 - if (!cpumask_test_and_clear_cpu(smp_processor_id(), 1427 - cpu_stat_off)) { 1428 - queue_delayed_work_on(smp_processor_id(), vmstat_wq, 1425 + queue_delayed_work_on(smp_processor_id(), vmstat_wq, 1429 1426 this_cpu_ptr(&vmstat_work), 1430 1427 round_jiffies_relative(sysctl_stat_interval)); 1431 - } 1432 - } else { 1433 - /* 1434 - * We did not update any counters so the app may be in 1435 - * a mode where it does not cause counter updates. 1436 - * We may be uselessly running vmstat_update. 1437 - * Defer the checking for differentials to the 1438 - * shepherd thread on a different processor. 1439 - */ 1440 - cpumask_set_cpu(smp_processor_id(), cpu_stat_off); 1441 1428 } 1442 1429 } 1443 1430 ··· 1455 1470 return false; 1456 1471 } 1457 1472 1473 + /* 1474 + * Switch off vmstat processing and then fold all the remaining differentials 1475 + * until the diffs stay at zero. The function is used by NOHZ and can only be 1476 + * invoked when tick processing is not active. 1477 + */ 1458 1478 void quiet_vmstat(void) 1459 1479 { 1460 1480 if (system_state != SYSTEM_RUNNING) 1461 1481 return; 1462 1482 1463 - /* 1464 - * If we are already in hands of the shepherd then there 1465 - * is nothing for us to do here. 1466 - */ 1467 - if (cpumask_test_and_set_cpu(smp_processor_id(), cpu_stat_off)) 1483 + if (!delayed_work_pending(this_cpu_ptr(&vmstat_work))) 1468 1484 return; 1469 1485 1470 1486 if (!need_update(smp_processor_id())) ··· 1479 1493 */ 1480 1494 refresh_cpu_vm_stats(false); 1481 1495 } 1482 - 1483 1496 1484 1497 /* 1485 1498 * Shepherd worker thread that checks the ··· 1496 1511 1497 1512 get_online_cpus(); 1498 1513 /* Check processors whose vmstat worker threads have been disabled */ 1499 - for_each_cpu(cpu, cpu_stat_off) { 1514 + for_each_online_cpu(cpu) { 1500 1515 struct delayed_work *dw = &per_cpu(vmstat_work, cpu); 1501 1516 1502 - if (need_update(cpu)) { 1503 - if (cpumask_test_and_clear_cpu(cpu, cpu_stat_off)) 1504 - queue_delayed_work_on(cpu, vmstat_wq, dw, 0); 1505 - } else { 1506 - /* 1507 - * Cancel the work if quiet_vmstat has put this 1508 - * cpu on cpu_stat_off because the work item might 1509 - * be still scheduled 1510 - */ 1511 - cancel_delayed_work(dw); 1512 - } 1517 + if (!delayed_work_pending(dw) && need_update(cpu)) 1518 + queue_delayed_work_on(cpu, vmstat_wq, dw, 0); 1513 1519 } 1514 1520 put_online_cpus(); 1515 1521 ··· 1515 1539 for_each_possible_cpu(cpu) 1516 1540 INIT_DEFERRABLE_WORK(per_cpu_ptr(&vmstat_work, cpu), 1517 1541 vmstat_update); 1518 - 1519 - if (!alloc_cpumask_var(&cpu_stat_off, GFP_KERNEL)) 1520 - BUG(); 1521 - cpumask_copy(cpu_stat_off, cpu_online_mask); 1522 1542 1523 1543 vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); 1524 1544 schedule_delayed_work(&shepherd, ··· 1550 1578 case CPU_ONLINE_FROZEN: 1551 1579 refresh_zone_stat_thresholds(); 1552 1580 node_set_state(cpu_to_node(cpu), N_CPU); 1553 - cpumask_set_cpu(cpu, cpu_stat_off); 1554 1581 break; 1555 1582 case CPU_DOWN_PREPARE: 1556 1583 case CPU_DOWN_PREPARE_FROZEN: 1557 1584 cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu)); 1558 - cpumask_clear_cpu(cpu, cpu_stat_off); 1559 1585 break; 1560 1586 case CPU_DOWN_FAILED: 1561 1587 case CPU_DOWN_FAILED_FROZEN: 1562 - cpumask_set_cpu(cpu, cpu_stat_off); 1563 1588 break; 1564 1589 case CPU_DEAD: 1565 1590 case CPU_DEAD_FROZEN: