tmpfs fills up, although hardly used. How can I debug this
I have a system with / on tmpfs. Most / subdirectories have aufs mounted overlaying the read-write root filesystem with read-only base filesystem (the system boots from a read-only medium). Earlier, I used to use unionfs instead of aufs. It has been working properly until recently the tmpfs started to fill up. I am not sure what triggered the change. It could be the unionfs to aufs change, a kernel upgrade or some changes in the system and how it accesses the file systems.
Anyway, it seems it is the tmpfs which behaves somehow wrong.
Although the system should not write a lot to tmpfs, quite a bit of it is used up:
# df -m /
Filesystem 1M-blocks Used Available Use% Mounted on
tmpfs 200 50 151 25% /
while:
# du -smx /
2 /
This is my test system, doing basically nothing. Things are wore on production system when usage quickly reach over 90% and the system crashes.
I would suspect these are deleted files still open, but:
# lsof | grep deleted
shows nothing.
The other idea was, that some files on / are masked by a file system mounted over it, so I tried this:
# mount --bind / /mnt
# du -sm /mnt
2 /mnt
Still, no trace of the 48MB lost.
How can I find out what is using up my tmpfs file system?
System information:
# uname -rm
3.4.6 i686
Update: I have tried kernels 3.4.17 and 3.6.6 – no change.
I have solved the mystery myself, with help of the aufs maintainer, Junjiro Okajima.
The first step, to debug the problem, was to reproduce it in a controlled way. It took me some time (now I wonder why so much) to find out, that the problem occurs when files are written and deleted via aufs.
Reproducing the problem
create mount points:
# cd /tmp
# mkdir rw
# mkdir mnt
mount the tmpfs:
# mount -t tmpfs none /tmp/rw
mount the aufs, overlaying /usr with /tmp/rw:
# mount -t aufs -n -o "br:/tmp/rw:/usr" none "/tmp/mnt"
now I can see /usr contents under /tmp/mnt:
# ls /tmp/mnt
bin games include lib lib64 local sbin share src
what I am interested in is the used/available space on the tmpfs below:
# du -sk /tmp/rw
0 /tmp/rw
# df /tmp/rw
Filesystem 1K-blocks Used Available Use% Mounted on
none 1031128 24 1031104 1% /tmp/rw
No files in /tmp/rw, but 24 blocks allocated. Still not a big problem.
I can write a file to the aufs, it will be stored on tmpfs in /tmp/rw:
# dd if=/dev/zero of=/tmp/mnt/test bs=1024 count=100
100+0 records in
100+0 records out
102400 bytes (102 kB) copied, 0.000343903 s, 298 MB/s
# du -sk /tmp/rw
100 /tmp/rw
# df /tmp/rw
Filesystem 1K-blocks Used Available Use% Mounted on
none 1031128 128 1031000 1% /tmp/rw
Note how the usage stats changed. du
show 100kB added, as expected, but the 'Used' value in the df
output increased by 104 blocks.
When I remove the file:
# du -sk /tmp/rw
0 /tmp/rw
# df /tmp/rw
Filesystem 1K-blocks Used Available Use% Mounted on
none 1031128 28 1031100 1% /tmp/rw
Four blocks are lost.
When I repeat the dd
and rm
commands a few times I get:
# df /tmp/rw
Filesystem 1K-blocks Used Available Use% Mounted on
none 1031128 36 1031092 1% /tmp/rw
More and more tmpfs blocks were gone and I didn't know where…
Where I did the same – dd
and rm
directly on /tmp/rw nothing was lost this way. And after un-mounting the aufs, the lost space on tmpfs was recovered. So, at least, I knew it was aufs, not tmpfs to blame.
What has been happening
Knowing what to blame, I described my problem on the aufs-users mailing list. I have quickly received first answers. The one from J. R. Okajima helped me to explain what is happening to the missing tmpfs blocks.
It was a deleted file, indeed. It wasn't shown by lsof
or anywhere in /proc/<pid>/*
as the file was not opened or mmaped by any user-space process. The file, the 'xino file', is aufs' external inode number translation table and is used internally by the kernel aufs module.
Path to the file can be read from sysfs:
# cat /sys/fs/aufs/si_*/xi_path
/tmp/rw/.aufs.xino
But, as the file is deleted, it cannot be seen directly:
# ls -l /tmp/rw/.aufs.xino
ls: cannot access /tmp/rw/.aufs.xino: No such file or directory
Though, information about its size and sizes of the other special aufs files can be read from the debugfs:
# for f in /sys/kernel/debug/aufs/si_8c8d888a/* ; do echo -n "$f: " ; cat $f ; done
/sys/kernel/debug/aufs/si_8c8d888a/xi0: 1, 32x4096 132416
/sys/kernel/debug/aufs/si_8c8d888a/xi1: 1, 24x4096 626868
/sys/kernel/debug/aufs/si_8c8d888a/xib: 8x4096 4096
/sys/kernel/debug/aufs/si_8c8d888a/xigen: 8x4096 88
The details are described in the aufs manual page.
The solution
The 'xino file' can be manually truncated by:
# mount -o remount,itrunc_xino=0 /tmp/mnt
Automatic xino file truncation can be requested by using trunc_xino option while mounting the aufs:
# mount -t aufs -n -o "br:/tmp/rw:/usr,trunc_xino" none "/tmp/mnt"
I still don't know how does it affect file system performance or if this will really solve my out-of-tmpfs-space problems on production… but I have learned a lot.
I have seen this happen where files were deleted but processes were still holding on to the file which meant that the space was not freed until the process was restarted. I have seen this with Apache Log files. It seemed to continue to write to the now deleted log file and the space was not cleared until it was restarted.
To find out which process might be holding on to deleted files, you might try restarting each process and see if that clears the space. If it does, you have found your culprit.
HTH