A single featurelet for delay accounting. Delayed a bit

because,unusually, it has dependencies on both the mm-stable and
 mm-nonmm-stable queues.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQTTMBEPP41GrTpTJgfdBJ7gKXxAjgUCYpz3SAAKCRDdBJ7gKXxA
 jou6AP9bY89NifR7Tc8U59Xu4c9amphXS9rTJv7Ysj3GxBMoRwEAuXvvJTet6mEn
 UdmytDdb4BtAlx7Itd7IKu4S9JD6mQw=
 =bAU1
 -----END PGP SIGNATURE-----

Merge tag 'mm-nonmm-stable-2022-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull delay-accounting update from Andrew Morton:
 "A single featurette for delay accounting.

  Delayed a bit because, unusually, it had dependencies on both the
  mm-stable and mm-nonmm-stable queues"

* tag 'mm-nonmm-stable-2022-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  delayacct: track delays from write-protect copy
This commit is contained in:
Linus Torvalds 2022-06-05 16:58:27 -07:00
commit e17fee8976
7 changed files with 76 additions and 3 deletions

View File

@ -15,6 +15,7 @@ c) swapping in pages
d) memory reclaim d) memory reclaim
e) thrashing page cache e) thrashing page cache
f) direct compact f) direct compact
g) write-protect copy
and makes these statistics available to userspace through and makes these statistics available to userspace through
the taskstats interface. the taskstats interface.
@ -48,7 +49,7 @@ this structure. See
for a description of the fields pertaining to delay accounting. for a description of the fields pertaining to delay accounting.
It will generally be in the form of counters returning the cumulative It will generally be in the form of counters returning the cumulative
delay seen for cpu, sync block I/O, swapin, memory reclaim, thrash page delay seen for cpu, sync block I/O, swapin, memory reclaim, thrash page
cache, direct compact etc. cache, direct compact, write-protect copy etc.
Taking the difference of two successive readings of a given Taking the difference of two successive readings of a given
counter (say cpu_delay_total) for a task will give the delay counter (say cpu_delay_total) for a task will give the delay
@ -117,6 +118,8 @@ Get sum of delays, since system boot, for all pids with tgid 5::
0 0 0ms 0 0 0ms
COMPACT count delay total delay average COMPACT count delay total delay average
0 0 0ms 0 0 0ms
WPCOPY count delay total delay average
0 0 0ms
Get IO accounting for pid 1, it works only with -p:: Get IO accounting for pid 1, it works only with -p::

View File

@ -45,9 +45,13 @@ struct task_delay_info {
u64 compact_start; u64 compact_start;
u64 compact_delay; /* wait for memory compact */ u64 compact_delay; /* wait for memory compact */
u64 wpcopy_start;
u64 wpcopy_delay; /* wait for write-protect copy */
u32 freepages_count; /* total count of memory reclaim */ u32 freepages_count; /* total count of memory reclaim */
u32 thrashing_count; /* total count of thrash waits */ u32 thrashing_count; /* total count of thrash waits */
u32 compact_count; /* total count of memory compact */ u32 compact_count; /* total count of memory compact */
u32 wpcopy_count; /* total count of write-protect copy */
}; };
#endif #endif
@ -75,6 +79,8 @@ extern void __delayacct_swapin_start(void);
extern void __delayacct_swapin_end(void); extern void __delayacct_swapin_end(void);
extern void __delayacct_compact_start(void); extern void __delayacct_compact_start(void);
extern void __delayacct_compact_end(void); extern void __delayacct_compact_end(void);
extern void __delayacct_wpcopy_start(void);
extern void __delayacct_wpcopy_end(void);
static inline void delayacct_tsk_init(struct task_struct *tsk) static inline void delayacct_tsk_init(struct task_struct *tsk)
{ {
@ -191,6 +197,24 @@ static inline void delayacct_compact_end(void)
__delayacct_compact_end(); __delayacct_compact_end();
} }
static inline void delayacct_wpcopy_start(void)
{
if (!static_branch_unlikely(&delayacct_key))
return;
if (current->delays)
__delayacct_wpcopy_start();
}
static inline void delayacct_wpcopy_end(void)
{
if (!static_branch_unlikely(&delayacct_key))
return;
if (current->delays)
__delayacct_wpcopy_end();
}
#else #else
static inline void delayacct_init(void) static inline void delayacct_init(void)
{} {}
@ -225,6 +249,10 @@ static inline void delayacct_compact_start(void)
{} {}
static inline void delayacct_compact_end(void) static inline void delayacct_compact_end(void)
{} {}
static inline void delayacct_wpcopy_start(void)
{}
static inline void delayacct_wpcopy_end(void)
{}
#endif /* CONFIG_TASK_DELAY_ACCT */ #endif /* CONFIG_TASK_DELAY_ACCT */

View File

@ -34,7 +34,7 @@
*/ */
#define TASKSTATS_VERSION 12 #define TASKSTATS_VERSION 13
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */ * in linux/sched.h */
@ -194,6 +194,10 @@ struct taskstats {
__u64 ac_exe_dev; /* program binary device ID */ __u64 ac_exe_dev; /* program binary device ID */
__u64 ac_exe_inode; /* program binary inode number */ __u64 ac_exe_inode; /* program binary inode number */
/* v12 end */ /* v12 end */
/* v13: Delay waiting for write-protect copy */
__u64 wpcopy_count;
__u64 wpcopy_delay_total;
}; };

View File

@ -177,11 +177,14 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
d->thrashing_delay_total = (tmp < d->thrashing_delay_total) ? 0 : tmp; d->thrashing_delay_total = (tmp < d->thrashing_delay_total) ? 0 : tmp;
tmp = d->compact_delay_total + tsk->delays->compact_delay; tmp = d->compact_delay_total + tsk->delays->compact_delay;
d->compact_delay_total = (tmp < d->compact_delay_total) ? 0 : tmp; d->compact_delay_total = (tmp < d->compact_delay_total) ? 0 : tmp;
tmp = d->wpcopy_delay_total + tsk->delays->wpcopy_delay;
d->wpcopy_delay_total = (tmp < d->wpcopy_delay_total) ? 0 : tmp;
d->blkio_count += tsk->delays->blkio_count; d->blkio_count += tsk->delays->blkio_count;
d->swapin_count += tsk->delays->swapin_count; d->swapin_count += tsk->delays->swapin_count;
d->freepages_count += tsk->delays->freepages_count; d->freepages_count += tsk->delays->freepages_count;
d->thrashing_count += tsk->delays->thrashing_count; d->thrashing_count += tsk->delays->thrashing_count;
d->compact_count += tsk->delays->compact_count; d->compact_count += tsk->delays->compact_count;
d->wpcopy_count += tsk->delays->wpcopy_count;
raw_spin_unlock_irqrestore(&tsk->delays->lock, flags); raw_spin_unlock_irqrestore(&tsk->delays->lock, flags);
return 0; return 0;
@ -249,3 +252,16 @@ void __delayacct_compact_end(void)
&current->delays->compact_delay, &current->delays->compact_delay,
&current->delays->compact_count); &current->delays->compact_count);
} }
void __delayacct_wpcopy_start(void)
{
current->delays->wpcopy_start = local_clock();
}
void __delayacct_wpcopy_end(void)
{
delayacct_end(&current->delays->lock,
&current->delays->wpcopy_start,
&current->delays->wpcopy_delay,
&current->delays->wpcopy_count);
}

View File

@ -32,6 +32,7 @@
#include <linux/cma.h> #include <linux/cma.h>
#include <linux/migrate.h> #include <linux/migrate.h>
#include <linux/nospec.h> #include <linux/nospec.h>
#include <linux/delayacct.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
@ -5230,6 +5231,8 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
pte = huge_ptep_get(ptep); pte = huge_ptep_get(ptep);
old_page = pte_page(pte); old_page = pte_page(pte);
delayacct_wpcopy_start();
retry_avoidcopy: retry_avoidcopy:
/* /*
* If no-one else is actually using this page, we're the exclusive * If no-one else is actually using this page, we're the exclusive
@ -5240,6 +5243,8 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
page_move_anon_rmap(old_page, vma); page_move_anon_rmap(old_page, vma);
if (likely(!unshare)) if (likely(!unshare))
set_huge_ptep_writable(vma, haddr, ptep); set_huge_ptep_writable(vma, haddr, ptep);
delayacct_wpcopy_end();
return 0; return 0;
} }
VM_BUG_ON_PAGE(PageAnon(old_page) && PageAnonExclusive(old_page), VM_BUG_ON_PAGE(PageAnon(old_page) && PageAnonExclusive(old_page),
@ -5309,6 +5314,7 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
* race occurs while re-acquiring page table * race occurs while re-acquiring page table
* lock, and our job is done. * lock, and our job is done.
*/ */
delayacct_wpcopy_end();
return 0; return 0;
} }
@ -5367,6 +5373,8 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
put_page(old_page); put_page(old_page);
spin_lock(ptl); /* Caller expects lock to be held */ spin_lock(ptl); /* Caller expects lock to be held */
delayacct_wpcopy_end();
return ret; return ret;
} }

View File

@ -3090,6 +3090,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
int page_copied = 0; int page_copied = 0;
struct mmu_notifier_range range; struct mmu_notifier_range range;
delayacct_wpcopy_start();
if (unlikely(anon_vma_prepare(vma))) if (unlikely(anon_vma_prepare(vma)))
goto oom; goto oom;
@ -3114,6 +3116,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
put_page(new_page); put_page(new_page);
if (old_page) if (old_page)
put_page(old_page); put_page(old_page);
delayacct_wpcopy_end();
return 0; return 0;
} }
} }
@ -3220,12 +3224,16 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
free_swap_cache(old_page); free_swap_cache(old_page);
put_page(old_page); put_page(old_page);
} }
delayacct_wpcopy_end();
return (page_copied && !unshare) ? VM_FAULT_WRITE : 0; return (page_copied && !unshare) ? VM_FAULT_WRITE : 0;
oom_free_new: oom_free_new:
put_page(new_page); put_page(new_page);
oom: oom:
if (old_page) if (old_page)
put_page(old_page); put_page(old_page);
delayacct_wpcopy_end();
return VM_FAULT_OOM; return VM_FAULT_OOM;
} }

View File

@ -207,6 +207,8 @@ static void print_delayacct(struct taskstats *t)
"THRASHING%12s%15s%15s\n" "THRASHING%12s%15s%15s\n"
" %15llu%15llu%15llums\n" " %15llu%15llu%15llums\n"
"COMPACT %12s%15s%15s\n" "COMPACT %12s%15s%15s\n"
" %15llu%15llu%15llums\n"
"WPCOPY %12s%15s%15s\n"
" %15llu%15llu%15llums\n", " %15llu%15llu%15llums\n",
"count", "real total", "virtual total", "count", "real total", "virtual total",
"delay total", "delay average", "delay total", "delay average",
@ -234,7 +236,11 @@ static void print_delayacct(struct taskstats *t)
"count", "delay total", "delay average", "count", "delay total", "delay average",
(unsigned long long)t->compact_count, (unsigned long long)t->compact_count,
(unsigned long long)t->compact_delay_total, (unsigned long long)t->compact_delay_total,
average_ms(t->compact_delay_total, t->compact_count)); average_ms(t->compact_delay_total, t->compact_count),
"count", "delay total", "delay average",
(unsigned long long)t->wpcopy_count,
(unsigned long long)t->wpcopy_delay_total,
average_ms(t->wpcopy_delay_total, t->wpcopy_count));
} }
static void task_context_switch_counts(struct taskstats *t) static void task_context_switch_counts(struct taskstats *t)