Let's create a 1 gig sparse file:
~ # cd /tmp tmp # ./sparse bla.img 1000000000 tmp #/tmp is a 4 GB tmpfs on a Gentoo box running Linux 3.5.0 x86_64. sparse (the tool to create the sparse file named bla.img) was compiled using cc -o sparse sparse.c. You might download sparse.c.
tmp # ls -l bla.img ; ls -s bla.img -rw-r--r-- 1 root root 1000000000 Sep 1 15:18 bla.img 4 bla.img tmp #That's what I expected. File size is 1 GB, actual size is 4 KiB.
tmp # losetup /dev/loop0 bla.img tmp # ls -l bla.img ; ls -s bla.img -rw-r--r-- 1 root root 1000000000 Sep 1 15:18 bla.img 332 bla.img tmp #Attaching the sparse file as a loop device consumes 328 KiB.
tmp # mkfs.ext4 /dev/loop0 mke2fs 1.42.5 (29-Jul-2012) Discarding device blocks: done Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 61056 inodes, 244140 blocks 12207 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=251658240 8 block groups 32768 blocks per group, 32768 fragments per group 7632 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done tmp # ls -l bla.img ; ls -s bla.img tmp # -rw-r--r-- 1 root root 1000000000 Sep 1 15:20 bla.img 16976 bla.img tmp #Ext4 metadata consumes almost 17 MiB.
tmp # ls -l bla.img ; ls -s bla.img -rw-r--r-- 1 root root 1000000000 Sep 1 15:21 bla.img 16976 bla.img tmp #Mounting is for free.
tmp # dd if=/dev/zero of=/mnt/foo.bar bs=1M count=80 oflag=sync 80+0 records in 80+0 records out 83886080 bytes (84 MB) copied, 0.0894017 s, 938 MB/s tmp # ls -l bla.img ; ls -s bla.img ; ls -l /mnt/foo.bar ; ls -s /mnt/foo.bar -rw-r--r-- 1 root root 1000000000 Sep 1 15:25 bla.img 98896 bla.img -rw-r--r-- 1 root root 83886080 Sep 1 15:25 /mnt/foo.bar 81920 /mnt/foo.bar tmp #Writing a 80 MiB file to the ext4 filesystem extends the sparse file by exactly 80 MiB.
tmp # rm /mnt/foo.bar tmp # ls -l bla.img ; ls -s bla.img /mnt/foo.bar -rw-r--r-- 1 root root 1000000000 Sep 1 15:25 bla.img 98896 bla.img tmp #Removing a file doesn't release any allocated blocks.
tmp # ls -l bla.img ; ls -s bla.img ; ls -l /mnt/foo.bar ; ls -s /mnt/foo.bar -rw-r--r-- 1 root root 1000000000 Sep 1 15:53 bla.img 98896 bla.img -rw-r--r-- 1 root root 83886080 Sep 1 15:53 /mnt/foo.bar 81920 /mnt/foo.bar tmp #Recreating the file after several minutes doesn't consume any additional space.
tmp # rm /mnt/foo.bar core tmp # dd if=/dev/zero of=/mnt/foo.bar bs=1M count=80 oflag=sync 80+0 records in 80+0 records out 83886080 bytes (84 MB) copied, 0.0860126 s, 975 MB/s tmp # ls -l bla.img ; ls -s bla.img ; ls -l /mnt/foo.bar ; ls -s /mnt/foo.bar -rw-r--r-- 1 root root 1000000000 Sep 1 15:54 bla.img 139856 bla.img -rw-r--r-- 1 root root 83886080 Sep 1 15:54 /mnt/foo.bar 81920 /mnt/foo.bar tmp #But recreating it within a minute requires 50% additional space.
tmp # umount /mnt tmp # ls -l bla.img ; ls -s bla.img -rw-r--r-- 1 root root 1000000000 Sep 1 16:01 bla.img 139856 bla.img tmp #Again, unmounting is for free.
tmp # mkfs.ext4 /dev/loop0 mke2fs 1.42.5 (29-Jul-2012) Discarding device blocks: done Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 61056 inodes, 244140 blocks 12207 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=251658240 8 block groups 32768 blocks per group, 32768 fragments per group 7632 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done tmp # ls -l bla.img ; ls -s bla.img -rw-r--r-- 1 root root 1000000000 Sep 1 16:02 bla.img 16976 bla.img tmp #Recreating the filesystem resets the space consumption. I didn't expect that.