Your 160 GB partition is 94.78 % full and its file system is using the default value for reserved block (5%).
You have then only 0.22% of your disk available (~40 MB). There is no much point trying to understand why a tiny file cause a disk full with so little space available.
You system might be at the same time creating log or temporary files that fill this space. Journaling might also play a role here. i.e. your tiny file isn't written directly but through an intermediary location that might require extra space.
Ext4 can use 1kB, 2kB or 4kB as the block size; as far as I know the default on Ubuntu is 4kB. Note that here, a block is the size of a file chunk, which is constant for a given filesystem. The file you describe has two blocks that are not zeroes: the one containing hello
(surrounded by a bunch of zeroes — 3616 before and 474 after), and the one containing here
(preceded by a bunch of zeroes, and containing only 3148 bytes, after which the end of the file is reached). The total is two blocks of 4kB.
In the ls
output, blocks are an arbitrary unit chosen by the ls
command and defaulting to 1kB. There are 2 blocks of 4kB each allocated to contain file data, therefore the allocated size for the file is 8kB.
Your confusion may be due to two things. First, the figure of 2048 bytes for a block is possible, but it's not the default value under Ubuntu (or most modern distributions), and it's apparently not the value on your system. You can check the block size by running tune2fs -l /dev/sdz42
(use the actual path to your filesystem device).
Second, sparse files consist of not storing blocks that are entirely made of zeroes. If a block (which is of necessity aligned on a block size boundary, at least for most filesystems including ext4) contains zeroes and other things, then the full block is stored on the disk. Thus, in that 40012-byte file (how did you get to 40013, by the way), there are 4 all-zero non-stored blocks, then one stored block containing hello
surrounded by zeroes, then 4 more all-zero non-stored blocks, and a final partial block containing zeroes and there
.
Note that your utility can be written in terms of standard shell commands:
n=20000
while IFS= read -r line; do
dd bs=1 seek=$n </dev/null
echo "$line"
done >testfile
Best Answer
I guess you got that one letter into the file with
echo a > file
orvim file
, which means, you'll have that letter and an additional newline in it (two characters, thus two bytes).ls -l
shows file size in bytes, not blocks (to be more specific: file length):(note that
cat -A
displays newlines as$
character)In contrast to
ls -l
,du
will show the real size occupied on disk:(actually,
du
shows size in 1kiB units, so here the size is 4×1024 bytes = 4096 bytes = 4 kiB, which is the block size on this file system)To have
ls
show this, you'll have to use the-s
option instead of/in addition to-l
:The first column is the allocated size, again in units of 1kiB. Last can be changed by specifying
--block-size
, e.g.