Ejemplo n.º 1
0
void FileSystemUnix::resolveIndirectDataBlocks(Inode* inode, sector_addr_t indirect_block, uint16 degree_of_indirection, uint16 sector_addr_len)
{
  if(indirect_block == UNUSED_DATA_BLOCK)
  {
    debug(FS_UNIX, "resolveIndirectDataBlocks - indirect_block is not in use - quit\n");
    return;
  }

  if(degree_of_indirection == 0)
  {
    debug(FS_UNIX, "resolveIndirectDataBlocks - sorry this method only works for indirect blocks - quit\n");
    return;
  }

  debug(FS_UNIX, "resolveIndirectDataBlocks - indirect_block %x deg_of_indirection=%d\n", indirect_block, degree_of_indirection);
  FileSystem* fs = inode->getFileSystem();
  assert(fs != NULL);
  FsVolumeManager* volume_manager = fs->getVolumeManager();
  assert(volume_manager != NULL);

  // lock sector for reading
  volume_manager->acquireDataBlockForReading(indirect_block);

  // readout sector data
  char* sector = volume_manager->readDataBlockUnprotected(indirect_block);

  // scan the current block for more indirect blocks
  for(sector_len_t i = 0; i < fs->getDataBlockSize(); i+= sector_addr_len)
  {
    sector_addr_t new_sector = 0;

    // reading the current sector entry in a very flexible way
    for(uint16 j = 0; j < sector_addr_len; j++)
    {
      //debug(FS_UNIX, "resolveIndirectDataBlocks - sector[%d + %d]=%x\n", i, j, (uint8)sector[i + j]);
      new_sector |= ((uint8)(sector[i + j])) << (8*j);
    }

    if(new_sector == UNUSED_DATA_BLOCK)
    {
      // from here on there are no more indirect blocks to resolve, we can quit
      debug(FS_UNIX, "resolveIndirectDataBlocks - quit search for indirect blocks\n");
      break;
    }

    debug(FS_UNIX, "resolveIndirectDataBlocks - new_sector=%x\n", new_sector);

    // single-indirect block means that the gained (resolved) sector-address
    // points to a data-block of the i_node
    if(degree_of_indirection == 1)
    {
      inode->addSector(new_sector);
    }
    else
    {
      resolveIndirectDataBlocks(inode, new_sector, degree_of_indirection-1, sector_addr_len);
    }
  }

  volume_manager->releaseReadDataBlock(indirect_block);
  delete[] sector;
}