The Linux Filesystem basics Part two

A filesystem can become ‘full’ and ‘run out of space’ either by (1) running out of all the free bytes, or (2) it can use up all the available inodes even when space is left for adding data.

Thought of making a test filesystem and check this.

We begin by making a file of size 500KB to hold our test filesystem.

[tony@localhost ~]$ su -
Password: 
[root@localhost ~]# dd if=/dev/zero of=~/inodeimage.img bs=1k count=500
500+0 records in
500+0 records out
512000 bytes (512 kB) copied, 0.00167129 s, 306 MB/s
[root@localhost ~]# ls -l inodeimage.img 
-rw-r--r--. 1 root root 512000 Aug 26 22:06 inodeimage.img

Make this file a loop device to mount it as a disk and work on it.

[root@localhost ~]# losetup -f inodeimage.img    # -f assigns the first free loop device
[root@localhost ~]# losetup -a                   # list all loopdevices to see if it worked
/dev/loop0: [fd01]:33392 (/root/inodeimage.img)

Make our test filesystem using mkfs

[root@localhost ~]# mkfs /dev/loop0
mke2fs 1.41.14 (22-Dec-2010)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
64 inodes, 500 blocks
25 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=524288
1 block group
8192 blocks per group, 8192 fragments per group
64 inodes per group

Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 35 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Make a directory to mount our test filesystem, and mount it.

[root@localhost ~]# mkdir ~/inodetmp
[root@localhost ~]# mount -t ext2 /dev/loop0 ~/inodetmp

Check the free inodes and free space available on our test filesystem.

[root@localhost ~]# df -i ~/inodetmp/
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/loop0                64      11      53   18% /root/inodetmp   #53 free inodes
[root@localhost ~]# df -h ~/inodetmp/
Filesystem            Size  Used Avail Use% Mounted on
/dev/loop0            487K   15K  447K   4% /root/inodetmp
[root@localhost inodetmp]# ls
lost+found

So 53 free inodes available. Lets fill that up by creating 53 small files.

[root@localhost inodetmp]# for i in {1..53} ;do dd if=/dev/zero of=file$i bs=1 count=1; done
1+0 records in
1+0 records out
..........
..........
1+0 records in
1+0 records out
1 byte (1 B) copied, 2.4928e-05 s, 40.1 kB/s

Now, lets try creating another file,

[root@localhost inodetmp]# touch newfile
touch: cannot touch `newfile': No space left on device

See that we have a lot of space remaining (393K free), but no inodes left. In essence our disk is ‘full’ and have ‘run out of space’.

[root@localhost inodetmp]# df -i ~/inodetmp/
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/loop0                64      64       0  100% /root/inodetmp
[root@localhost inodetmp]# df -h ~/inodetmp/
Filesystem            Size  Used Avail Use% Mounted on
/dev/loop0            487K   69K  393K  15% /root/inodetmp

—————–

Ok. Lets now try to fill the disk by the other method, ie, by using all the available bytes.

Remove all those files,

[root@localhost inodetmp]# rm -f *
rm: cannot remove `lost+found': Is a directory
[root@localhost inodetmp]# df -h ~/inodetmp/
Filesystem            Size  Used Avail Use% Mounted on
/dev/loop0            487K   15K  447K   4% /root/inodetmp
[root@localhost inodetmp]# df -i ~/inodetmp/
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/loop0                64      11      53   18% /root/inodetmp

We see that 53 inodes are free and 447K is available, lets make a file of that size.

[root@localhost inodetmp]# dd if=/dev/zero of=file bs=1k count=447
447+0 records in
447+0 records out
457728 bytes (458 kB) copied, 0.00132163 s, 346 MB/s
[root@localhost inodetmp]# df -h ~/inodetmp/
Filesystem            Size  Used Avail Use% Mounted on
/dev/loop0            487K  466K     0 100% /root/inodetmp

We now see that the ‘Available’ space is 0. But if you check carefully the output, we see that the disk ‘Size’ is 487K and ‘Used’ is 466K. So remaining 21K??

Lets try making another file,

[root@localhost inodetmp]# dd if=/dev/zero of=file2 bs=1K count=1
1+0 records in
1+0 records out
1024 bytes (1.0 kB) copied, 3.0609e-05 s, 33.5 MB/s

It was possible eventhough 0 space was shown available!
This is because 5% of disk space is reserved for super user use. And df doesnt show that space as available in its output. This explains the difference 21K.

Lets fill that up too,

[root@localhost inodetmp]# dd if=/dev/zero of=file2 bs=1k count=20
20+0 records in
20+0 records out
20480 bytes (20 kB) copied, 0.000121892 s, 168 MB/s

[root@localhost inodetmp]# df -h ~/inodetmp/
Filesystem            Size  Used Avail Use% Mounted on
/dev/loop0            487K  487K     0 100% /root/inodetmp
[root@localhost inodetmp]# df -i ~/inodetmp/
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/loop0                64      13      51   21% /root/inodetmp

Try adding a 1byte file, it must fail.

[root@localhost inodetmp]# dd if=/dev/zero of=file3 bs=1 count=1
dd: writing `file3': No space left on device
1+0 records in
0+0 records out
0 bytes (0 B) copied, 0.000197034 s, 0.0 kB/s

See that we have a lot of inodes remaining (51 free ) but no bytes left. In essence our disk is ‘full’ and have ‘run out of space’.

—————

As we have inodes remaining, It might still be possible to create empty (size 0 bytes) files.

[root@localhost inodetmp]# touch emptyfile
[root@localhost inodetmp]# ls -l
total 485
-rw-r--r--. 1 root root      0 Aug 29 15:44 emptyfile
-rw-r--r--. 1 root root 457728 Aug 27 23:05 file
-rw-r--r--. 1 root root  20480 Aug 27 23:05 file2
drwx------. 2 root root  12288 Aug 26 22:06 lost+found

I was wondering where there is space to create the directory entry for this newly created filename. It seems that the filesystem reserves some datablocks for the use of directories when the filesystem is created. If more space is needed, it is allocated dynamically from the unused datablocks, if available.

Just wanted to see how many files can made before that reserved space gets filled up in our test filesystem.
We try to make 50 empty files with 255 character long random filename.

[root@localhost inodetmp]# for i in {1..50} ; do name=`cat /dev/urandom | tr -cd 'a-f0-9' | head -c 255`; touch "$name"; done

The screen scrolled and the script terminated displaying “No space left on the disk”

As we can see below, the reserved space was over with just 3 of our empty files.

[root@localhost inodetmp]# ls -1 | wc -l
7              # 3 new files were made, excluding the existing 4.

————

Thankyou, if you were patient to read so far! :D I appreciate it.

Leave a Reply

Your email address will not be published. Required fields are marked *


five − = 1

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>