Final Year Project:
Using Linux Filesystems Under Windows
Chris Bryden
BEng. Electronics and Software Engineering
School of Computer Science
University of Birmingham
39
Where ulBlkSize is the block size, ulBlock is the block address of the requested
block.
The main bottleneck to the performance of the ext2lib library is in reading
from disk. This is a slow operation as the hard disk is many times slower than
accessing memory. To minimise the number of disk reads that must be
performed, the readblock function implements two caches of blocks.
5.11.1 The Read-Ahead Cache
It was observed during testing that many disk accesses require a number
of contiguous blocks to be read from the disk, especially when reading
directories or files from the ext2 filesystem. It is for this reason that a read-ahead
cache was implemented. When a request to read a block form disk is first
received by the ReadBlock function, it not only reads the block requested, but
also reads CACHE_SIZE blocks (currently 8 blocks) ahead and buffers these blocks
in memory. This does not really take much more time than reading one block, as
the blocks being read are contiguous, the number of seeks that the disk head
has to make is minimised. An index to the cache holds the block addresses of
the cached blocks in an array.
The next time a block is requested, the ReadBlock function checks the
cache index to determine if the requested block is cached, and if it is, simply
reads it from memory, rather than accessing the disk again, which provides a
great boost to performance. If the block is not cached, the block is read from disk
and the read-ahead cache is re-filled.
5.11.2 The FIFO Cache
Whilst navigating the filesystem using the cd command and ls command
to read directories, blocks that were requested maybe two or three requests ago
are again requested from the ReadBlock function. It would provide a boost to
performance if these blocks were cached, as they would not have to be re-read
form disk. It is for this reason that the FIFO cache was implemented. It buffers
the last CACHE_SIZE (currently 8) requested blocks in memory. Each time a new
block is requested, the index for the FIFO cache is checked, and if the block has
been cached it is simply copied from the cache. If a block is not in the FIFO
cache, it is read from disk and the last block requested (the first block in the
read-ahead cache) is stored in the next position in the FIFO cache. If the cache
is full, the next cached block is written at the beginning of the cache.
The diagram below illustrates how these two caches operate in the readblock
function: