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: