Re: QUOTA [with patch this time]

Scott Jennings (smj@oro.net)
17 Dec 1996 00:49:28 GMT


There seems to be a bug in kernel quotas. I've verified that it is present
in the first 1.3.x kernels to support quotas.

The bug causes files copied or chowned to certain UID's to be
counted twice in their quota, that is a 10MB file will consume
20MB of their quota, conversly deleting the 10MB file will free
20MB of their quota.

It happens on roughly every 40th UID, but not exactly. I've
verified this on four different machines with various kernels
from 1.3.x to 2.1.15.

This script will make the problem obviuos by creating a small
file, and chowning it to each UID in sequence, noting the
difference in their quota it produces. Over here, it usually
shows the bug by UID=19. The failing UIDs will be constant on
any given filesystem, accross multiple kernels, but will vary
from filesystem to filesystem. Following the script is a sample
output from running it on one of our systems.

------------------------------------------------------------------------------
#! /bin/bash
#

TUID=0
LAST=${TUID}
FILESYSTEM=`df . | tail -1 | sed -e s/' .*$'// -e s/'^.*\/'//`
JUNKFILE=junk.delete
JUNKSIZE=500
LOGFILE=quota.oops

>${LOGFILE}
let COUNT=${JUNKSIZE}-3
dd if=/dev/zero of=${JUNKFILE} bs=1024 count=${COUNT}
chown bin:bin ${JUNKFILE}

while [ ${TUID} -lt 65534 ]
do
Q1=`quota -v ${TUID} | grep ${FILESYSTEM} \
| sed -e s/"^.*${FILESYSTEM} *"// -e s/' .*$'// | tr -d '*'`
chown ${TUID}:${TUID} ${JUNKFILE}
Q2=`quota -v ${TUID} | grep ${FILESYSTEM} \
| sed -e s/"^.*${FILESYSTEM} *"// -e s/' .*$'// | tr -d '*'`

let QD=${Q2}-${Q1}

echo -ne "${TUID}:(`grep "\*:${TUID}:" /etc/passwd | sed s/':.*$'//`) ${Q2} - ${Q1} = ${QD} \|\r"
if [ "${QD}" != "${JUNKSIZE}" ]
then
let DIFF=${TUID}-${LAST}
LAST=${TUID}
echo -ne " \r"
echo "${TUID}:(`grep "\*:${TUID}:" /etc/passwd | sed s/':.*$'//`) [${DIFF}] ${Q2} - ${Q1} = ${QD}"
echo "${TUID}:(`grep "\*:${TUID}:" /etc/passwd | sed s/':.*$'//`) [${DIFF}] ${Q2} - ${Q1} = ${QD}" >>${LOGFILE}
fi
let TUID=${TUID}+1
done

------------------------------------------------------------------------------

here is a sample output.
Note how the affected UID are frequently 45 apart.

# ./quotatest
497+0 records in
497+0 records out
19:() [19] 1000 - 0 = 1000
56:() [37] 1000 - 0 = 1000
101:(qmaild) [45] 1000 - 0 = 1000
146:() [45] 1000 - 0 = 1000
191:() [45] 1000 - 0 = 1000
228:() [37] 1000 - 0 = 1000
. . .