try to fix RACCT_RSS accounting

There could be a race between the vm daemon setting RACCT_RSS based on
the vm space and vmspace_exit (called from exit1) resetting RACCT_RSS to
zero.  In that case we can get a zombie process with non-zero RACCT_RSS.
If the process is jailed, that may break accounting for the jail.
There could be other consequences.

Fix this race in the vm daemon by updating RACCT_RSS only when a process
is in the normal state.  Also, make accounting a little bit more
accurate by refreshing the page resident count after calling
vm_pageout_map_deactivate_pages().
Finally, add an assert that the RSS is zero when a process is reaped.

PR:		210315
Reviewed by:	trasz
Differential Revision: https://reviews.freebsd.org/D9464
This commit is contained in:
Andriy Gapon 2017-02-14 13:54:05 +00:00
parent 00ef17befe
commit 937c1b0757
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313730
2 changed files with 9 additions and 3 deletions

View File

@ -1010,10 +1010,13 @@ racct_proc_exit(struct proc *p)
racct_set_locked(p, RACCT_CPU, runtime, 0);
racct_add_cred_locked(p->p_ucred, RACCT_PCTCPU, pct);
KASSERT(p->p_racct->r_resources[RACCT_RSS] == 0,
("process reaped with %ju allocated for RSS\n",
p->p_racct->r_resources[RACCT_RSS]));
for (i = 0; i <= RACCT_MAX; i++) {
if (p->p_racct->r_resources[i] == 0)
continue;
if (!RACCT_IS_RECLAIMABLE(i))
if (!RACCT_IS_RECLAIMABLE(i))
continue;
racct_set_locked(p, i, 0, 0);
}

View File

@ -2268,12 +2268,14 @@ vm_daemon(void)
if (size >= limit) {
vm_pageout_map_deactivate_pages(
&vm->vm_map, limit);
size = vmspace_resident_count(vm);
}
#ifdef RACCT
if (racct_enable) {
rsize = IDX_TO_OFF(size);
PROC_LOCK(p);
racct_set(p, RACCT_RSS, rsize);
if (p->p_state == PRS_NORMAL)
racct_set(p, RACCT_RSS, rsize);
ravailable = racct_get_available(p, RACCT_RSS);
PROC_UNLOCK(p);
if (rsize > ravailable) {
@ -2299,7 +2301,8 @@ vm_daemon(void)
size = vmspace_resident_count(vm);
rsize = IDX_TO_OFF(size);
PROC_LOCK(p);
racct_set(p, RACCT_RSS, rsize);
if (p->p_state == PRS_NORMAL)
racct_set(p, RACCT_RSS, rsize);
PROC_UNLOCK(p);
if (rsize > ravailable)
tryagain = 1;