示例#1
0
int soAllocDataCluster(uint32_t nInode, uint32_t *p_nClust) {
    soColorProbe(613, "07;33", "soAllocDataCluster (%"PRIu32", %p)\n", nInode, p_nClust);

    int stat; // variavel para o estado de erro
    //uint32_t nClust, clusterStat, NFClt; //variaveis para localizar o cluster, contem variavel extra usada no teste de consistencia do header do cluster
    SOSuperBlock *p_sb; //ponteiro para o superbloco
    SODataClust cluster; //ponteiro para o cluster que vai ser reservado
    SOInode *p_inode;
    uint32_t nBlock, offset, nClust, clusterStat, NFClt;

    //carregar o super bloco
    if ((stat = soLoadSuperBlock()) != 0)
        return stat;

    p_sb = soGetSuperBlock();

    //if ((stat = soQCheckSuperBlock(p_sb)) != 0)
    //    return stat;

    if ((stat = soQCheckDZ(p_sb)) != 0)
        return stat;

    //carregar inode pretendido
    if ((stat = soConvertRefInT(nInode, &nBlock, &offset)) != 0)
        return stat;

    if ((stat = soLoadBlockInT(nBlock)) != 0)
        return stat;

    p_inode = soGetBlockInT();

    //teste de consistencia ao inode
    if ((stat = soQCheckInodeIU(p_sb, &p_inode[offset])) != 0)
        return stat;

    //guardar o inode so precisavamos de testar a consistencia
    if ((stat = soStoreBlockInT()) != 0)
        return stat;

    //teste se o inode pretendido de encontra dentro dos valores possiveis e se o ponteiro nao vem com NULL_CLUSTER associado
    if (nInode > p_sb->iTotal - 1 || p_nClust == NULL)
        return -EINVAL;

    //verificar se ha clusters livres
    if (p_sb->dZoneFree == 0)
        return -ENOSPC;

    //se a cache estiver vazia, enche-la
    if (p_sb->dZoneRetriev.cacheIdx == DZONE_CACHE_SIZE)
        soReplenish(p_sb);

    //carregar o super bloco
    if ((stat = soLoadSuperBlock()) != 0)
        return stat;

    p_sb = soGetSuperBlock();

    //nclust = numero logico do cluster
    nClust = p_sb->dZoneRetriev.cache[p_sb->dZoneRetriev.cacheIdx]; // passar o numero do proximo cluster livre para nClust

    //teste de consistencia ao proximo cluster a reservar
    if ((stat = soQCheckStatDC(p_sb, nClust, &clusterStat)) != 0)
        return stat;
    
    //ir buscar o cluster nClust. nClust precisa de ser o numero fisico
    //relação entre numero fisico e numero logico
    //NFClt = dzone_start + NLClt * BLOCKS_PER_CLUSTER;
    NFClt = p_sb->dZoneStart + nClust * BLOCKS_PER_CLUSTER;

    if ((stat = soReadCacheCluster(NFClt, &cluster)) != 0)
        return stat;
    
    // codigo deste if, vem do pdf "manipulacao do cluster de dados", slide 23
    // check if the data cluster is dirty
    if (cluster.stat != NULL_INODE) {
        if ((stat = soCleanDataCluster(cluster.stat, nClust)) != 0)
            return stat;
    }
    

    p_sb->dZoneRetriev.cache[p_sb->dZoneRetriev.cacheIdx] = NULL_CLUSTER; //esse cluster já nao vai estar disponivel, por isso NULL_CLUSTER
    p_sb->dZoneRetriev.cacheIdx += 1;
    p_sb->dZoneFree -= 1;

    cluster.prev = cluster.next = NULL_CLUSTER;
    cluster.stat = nInode;

    //atribuir o numero do cluster ao ponteiro fornecido nos argumentos para esse efeito
    *p_nClust = nClust;

    //voltar a guardar o cluster
    if ((stat = soWriteCacheCluster(NFClt, &cluster)) != 0)
        return stat;

    //voltar a guardar o super bloco
    if ((stat = soStoreSuperBlock()) != 0)
        return stat;

    return 0;
}
int soAllocInode (uint32_t type, uint32_t* p_nInode)
{
  soProbe (411, "soAllocInode (%"PRIu32", %p)\n", type, p_nInode);
  
  /** Variables **/
  int status;
  SOSuperBlock *sb;
  SOInode *headInode;
  SOInode *nextInode;
  uint32_t headBlock;
  uint32_t nextBlock;
  uint32_t headOffset;
  uint32_t nextOffset;
  uint32_t nInode;

  /** Parameter check **/
  if((type != INODE_DIR) && (type != INODE_FILE) && (type != INODE_SYMLINK))
    return -EINVAL;
  if(p_nInode == NULL)
    return -EINVAL;

  /** Loading SuperBlock **/
  if((status = soLoadSuperBlock()) != 0)
    return status;
  if((sb = soGetSuperBlock()) == NULL)
    return -EBADF;

  /** Inode table consistency check **/
  if((status = soQCheckInT(sb)) != 0)
    return status;

  /** Check if there are free inodes **/
  if(sb->ifree == 0)
    return -ENOSPC;

  /** Obtain Block number and inode offset **/
  if((status = soConvertRefInT(sb->ihead, &headBlock, &headOffset)) != 0)
    return status;
  /** Read head inode from inode table **/
  if((status = soLoadBlockInT(headBlock)) != 0)
    return status;
  headInode = soGetBlockInT();

  /** Check if inode is free **/
  if((status = soQCheckFInode(&headInode[headOffset])) != 0)
    return status;

  /** Allocated inode number **/
  nInode = sb->ihead;  

  /**Update Superblock reference to head of double-linked list of free headInodes**/
  if(sb->ifree == 1)
  {
    sb->ihead = NULL_INODE;
    sb->itail = NULL_INODE;
  }
  else
    sb->ihead = headInode[headOffset].vD1.next;

  /** Update next inode information **/
  if(sb->ihead != NULL_INODE)
  {
    if((status = soConvertRefInT(sb->ihead, &nextBlock, &nextOffset)) != 0)
      return status;
    if((status = soLoadBlockInT(nextBlock)) != 0)
      return status;
    nextInode = soGetBlockInT();
    nextInode[nextOffset].vD2.prev = NULL_INODE;
    if((status = soStoreBlockInT()) != 0)
      return status;
  }

  /** Update and write superblock **/
  sb->ifree--;
  if((status = soStoreSuperBlock()) != 0)
    return status;

  /** "Re-Obtain" Block number and inode offset **/
  if((status = soConvertRefInT(nInode, &headBlock, &headOffset)) != 0)
    return status;
  /** "Re-Read" head inode from inode table **/
  if((status = soLoadBlockInT(headBlock)) != 0)
    return status;
  headInode = soGetBlockInT();

  /** Check if headInode is in dirty state **/
  if((status = soQCheckFCInode(&headInode[headOffset])) != 0)
  {
    if((status = soCleanInode(headBlock * IPB + headOffset)) != 0)
      return status;
    /*Since inode was updated, it will be readed again*/
    if((status = soConvertRefInT(nInode, &headBlock, &headOffset)) != 0)
      return status;
    /*Read head inode from inode table*/
    if((status = soLoadBlockInT(headBlock)) != 0)
      return status;
    headInode = soGetBlockInT();
  }

  /** Allocate headInode **/
  headInode[headOffset].mode = type;
  headInode[headOffset].refcount = 0;
  headInode[headOffset].owner = getuid();
  headInode[headOffset].group = getgid();
  headInode[headOffset].size = 0;
  headInode[headOffset].clucount = 0;
  headInode[headOffset].vD1.atime = time(NULL);
  headInode[headOffset].vD2.mtime = headInode[headOffset].vD1.atime;

  /*Write updated inode information to disk*/
  if((status = soStoreBlockInT()) != 0)
    return status;
  /*Consistency check*/
  if((status = soQCheckInodeIU(sb, &headInode[headOffset])) != 0)
    return status;

  /** Operation successful **/
  *p_nInode = nInode;
  return 0;
}
    int soAllocInode (uint32_t type, uint32_t* p_nInode)
    {
            soColorProbe (611, "07;31", "soAllocInode (%"PRIu32", %p)\n", type, p_nInode);

        	SOInode *array;
        	SOSuperBlock *p_sb;
        	uint32_t numBlock, offset, next;
        	int status, i;

            // Se o type não existe ou ponteiro p_nInode é nulo
        	if((type !=  INODE_DIR && type != INODE_FILE && type != INODE_SYMLINK) || p_nInode == NULL)
        		return -EINVAL;

        	// Superbloco na memória
        	if((status = soLoadSuperBlock()) != 0)
        		return status;

        	// Ponteiro do superbloco
        	if (!(p_sb = soGetSuperBlock()))
        		return -EIO;

        	// Tem de haver pelo menos um nó livre na lista de nós livres
        	if(p_sb->ifree == 0)
        	{
        		return -ENOSPC;
        	}

        	// Verifica se a tabela de inodes esta consistente
        	if ((status = soQCheckSuperBlock(p_sb)) != 0)
        	{
        		return status;
        	}
        	*p_nInode = p_sb->ihead;

        	// Obter nº bloco e o offset do inode
        	if ((status = soConvertRefInT(p_sb->ihead, &numBlock, &offset)))
        	{
        		return status;
        	}

        	// Ler o bloco do primeiro nó livre
        	if ((status = soLoadBlockInT(numBlock)))
        	{
        		return status;
        	}

        	array = soGetBlockInT();
        	next = array[offset].vD2.next;

        	// Preenchimento
        	array[offset].mode = type | 0x0;
        	array[offset].refcount = 0;
        	array[offset].owner = getuid();
        	array[offset].group = getgid();
        	array[offset].size = 0;
        	array[offset].clucount = 0;

        	for (i = 0; i < N_DIRECT; i++)
        	{
        		array[offset].d[i] = NULL_CLUSTER;
        	}

        	array[offset].i1 = NULL_CLUSTER;
        	array[offset].i2 = NULL_CLUSTER;

        	array[offset].vD1.atime = time(NULL);
        	array[offset].vD2.mtime = time(NULL);

        	// Algoritmo
        	if (p_sb->ifree == 1)
        	{
            	// A lista só tem um elemento
        		p_sb->ihead = NULL_INODE;
        		p_sb->itail = NULL_INODE;
        		if ((status = soStoreBlockInT()) != 0)
        		{
        			return status;
        		}
        	}
        	else{
        		// A lista tem dois ou mais elementos

        		// Actualiza ihead do bloco
        		p_sb->ihead = next;

        		// Guarda o inode
        		if ((status = soStoreBlockInT()) != 0)
        		{
        			return status;
        		}
        		// Nº Bloco e Offset inode head
        		if ((status = soConvertRefInT (next, &numBlock, &offset)) != 0)
        		{
        			return status;
        		}
        		// Como a lista não está vazia, vamos alterar o ihead
        		if ((status = soLoadBlockInT(numBlock)) != 0)
        		{
        			return status;
        		}
        		array = soGetBlockInT();
        		array[offset].vD1.prev = NULL_INODE;

        		// Guarda o inode
        		if ((status = soStoreBlockInT()) != 0)
        		{
        			return status;
        		}
        	}

        	// Decrementa o numero de free inodes
        	p_sb->ifree--;

        	// Guarda inode
        	if ((status = soStoreSuperBlock()) != 0)
        	{
        		return status;
        	}
        return 0;
    }