Final Year Project: Using Linux Filesystems Under Windows   Chris Bryden BEng. Electronics and Software Engineering    School of Computer Science   University of Birmingham 42 contained  within  this    group.  To  calculate  the  exact  block  required,  the  inode offset  is  divided  by  the  number  of  inodes  per  block,  this  gives  a  block  offset within  the  inode  table.  This  result  is  added  to  the  bg_inode_table  value  to produce the final block address of the block containing the required inode. The  block  containing  the  inode  can  now  be  read  into  a  memory  buffer using the ReadBlock function. To aid performance the GetInode function caches the last block that was read by the previous call to the function. If the next inode is from the same block, no disk read is necessary as the block is already cached in memory and can be reused. The  final  task  for  this  function  to  perform  is  copying  the  specified  inode from the block buffer to the Inode variable. The byte offset off the required inode within  the  buffered  block  has  to  be  calculated,  however.  This  is  achieved  as shown below: The first result that is required is the number of inodes that are in the buffered block  before  the  required  inode.  This  is  calculated  by  first  determining  the number  of  blocks  in  the  inode  table  that  lie  before  the  buffered  block.  This  is achieved  by  subtracting  the  block  address  of  the  beginning  of  the  inode  table, bg_inode_table, from the block address of the buffered block, ulBlock. This result is then multiplied by the number of inodes per block, ulInodesPerBlk,  to give the number of inodes that lie in the blocks before the buffered block. This result is then  subtracted  from  the  inode  offset,  ulINodeOffset,    minus  1.  This  gives  the number  of  inodes  that  are  in  the  buffered  block  before  the  required  inode,  the result that  is required. This is then simply multiplied by the size of an inode to give the byte offset. This  byte  offset  is  then  used  to  copy  the  desired  inode  from  the  block buffer into the Inode structure. 5.15  Layer 1: The GetBlockList Function This function is used to read the complete list of block addresses for the blocks  that  are  allocated  by  a  particular  inode.  These  are  the  direct  blocks, contained within the inode itself, and also the indirect, double indirect and triple indirect  blocks.  The  function  reads  the  list  of  block  addresses  into  a  memory buffer and returns a pointer to this buffer, lpBlocksBuff. The memory required for the   block   buffer   is   dynamically   expanded   according   to   how   many   block addresses  are  read  into  it  and  an  offset,  ulBuffOffset,    (measured  in  unsigned //calculate offset of desired inode within buffered block ulBlkOffset = sizeof(INODE) * (ulInodeOffset - 1 - ((ulBlock   - GroupDesc.bg_inode_table) * ulInodesPerBlk));