Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jun 2005 23:39:52 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Wietse Venema <wietse@porcupine.org>
Cc:        freebsd-bugs@freebsd.org, freebsd-gnats-submit@freebsd.org
Subject:   Re: kern/82682: "Accounting resumed" while disk fills up
Message-ID:  <20050627231610.F37130@delplex.bde.org>
In-Reply-To: <200506262005.j5QK5MQr019120@www.freebsd.org>
References:  <200506262005.j5QK5MQr019120@www.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 26 Jun 2005, Wietse Venema wrote:

>> Description:
> When the disk fills up, the kernel as expected disables process accounting, but it RESUMES process accounting while the disk fills up further.
>
> Perhaps the code gets confused when the free space becomes negative (see repeat-by example below). But that is pure speculation.
>
> I have been using FreeBSD for 10+ years and routinely use dd of /dev/zero to wipe the free space as root. I did not notice this accounting anomaly when I was still using FreeBSD 4.

This is one one the many possible and actual sign extension/overflow bugs
caused by the poorly chosen types in the 64-bit statfs.  From kern_acct.c:

%%%
 		if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
 			acctp = savacctp;
 			acctcred = savacctcred;
 			acctflags = savacctflags;
 			savacctp = NULLVP;
 			savacctcred = NOCRED;
 			log(LOG_NOTICE, "Accounting resumed\n");
 		}
%%%

In RELENG_4, everything in struct statfs has a non-foot-shooting type
(plain long), but in -current after 2003/12/11 the types don't mesh
properly; most types are 64 bits; f_bavail is still signed, as it needs
to be to represent negative free space, but most of the other types
are unsigned, as they need to be to cause sign extension bugs.  In the
above, `acctresume * sb.f_blocks / 100' has type uint64_t and is not
very large, but sb.f_bavail has type int64_t and is not very large in
absolute value, so as soon as sb.f_bavail becomes negative it is converted
to a huge uint64_t as part of the comparison and the comparison always
succeeds.

Another bug in the above is that `acctresume * sb.f_blocks' overflows if
sb.f_blocks exceeds 1/4 of the maximum for the data type.  This overflow
is hard to reach since (2^64)/4-1 blocks should be enough for anyone, and
even overflow at (2^31)/4 blocks in RELENG_4 is hard to reach due to
other limits (mainly the limit of 2^31-1 512-blocks).

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050627231610.F37130>