int soAttachLogicalCluster(SOSuperBlock *p_sb, uint32_t nInode, uint32_t clustInd, uint32_t nLClust) {

    int stat; // function return control
    uint32_t ind_prev, ind_next; // logical cluster number of adjacent clusters
    SODataClust dc, dc_prev, dc_next; // data clusters to be updated
    

    /* temos de verificar se o prev está bem ligado e se o next tambem esta bem ligado */
    if (clustInd == 0) {
        ind_prev = NULL_CLUSTER;
    } else {
        if ((stat = soHandleFileCluster(nInode, clustInd - 1, GET, &ind_prev)) != 0) {
            return 0;
        }

        if (ind_prev != NULL_CLUSTER) {
            if ((stat = soReadCacheCluster(p_sb->dZoneStart + ind_prev * BLOCKS_PER_CLUSTER, &dc_prev)) != 0) {
                return stat;
            }
        }
    }

    if (clustInd == MAX_FILE_CLUSTERS) {
        ind_next = NULL_CLUSTER;
    } else {
        if ((stat = soHandleFileCluster(nInode, clustInd + 1, GET, &ind_next)) !=0 ) {
            return 0;
        }

        if (ind_next != NULL_CLUSTER) {
            if ((stat = soReadCacheCluster(p_sb->dZoneStart + ind_next * BLOCKS_PER_CLUSTER, &dc_next)) != 0) {
                return stat;
            }
        }
    }

    if ((ind_prev != NULL_CLUSTER || ind_next != NULL_CLUSTER)) {
        if ((stat = soReadCacheCluster(p_sb->dZoneStart + nLClust * BLOCKS_PER_CLUSTER, &dc)) != 0) {
            return stat;
        }
        if (ind_prev != NULL_CLUSTER) {
            dc.prev = ind_prev;
            dc_prev.next = nLClust;
            if ((stat = soWriteCacheCluster(p_sb->dZoneStart + ind_prev * BLOCKS_PER_CLUSTER, &dc_prev)) != 0) {
                return stat;
            }
        }
        if (ind_next != NULL_CLUSTER) {
            dc.next = ind_next;
            dc_next.prev = nLClust;
            if ((stat = soWriteCacheCluster(p_sb->dZoneStart + ind_next * BLOCKS_PER_CLUSTER, &dc_next)) !=0 ) {
                return stat;
            }
        }
        if ((stat = soWriteCacheCluster(p_sb->dZoneStart + nLClust * BLOCKS_PER_CLUSTER, &dc)) != 0) {
            return stat;
        }
    }
    return 0;
}
int soReadFileCluster (uint32_t nInode, uint32_t clustInd, SODataClust *buff)
{
  soColorProbe (411, "07;31", "soReadFileCluster (%"PRIu32", %"PRIu32", %p)\n", nInode, clustInd, buff);

  int stat, i;
  SOSuperBlock *p_sb;
  SODataClust cluster;
  uint32_t numDC, nFClust;

  if( (stat = soLoadSuperBlock()) != 0){
    return stat;
  }

  p_sb = soGetSuperBlock();

  if(nInode >= p_sb->iTotal){
    return -EINVAL;  
  }

  if(buff == NULL){
    return -EINVAL;
  }

  if(clustInd >= MAX_FILE_CLUSTERS){
    return -EINVAL;
  }

  if((stat = soHandleFileCluster(nInode, clustInd, GET, &numDC)) != 0){
    return stat;
  }

  if(numDC == NULL_CLUSTER){
      for(i = 0; i < BSLPC; i++)
      {
        buff->info.data[i] = '\0';
      }
  }
  else{
    nFClust = p_sb->dZoneStart + numDC * BLOCKS_PER_CLUSTER; 

    if( (stat = soReadCacheCluster(nFClust, &cluster)) != 0){
      return stat;
    }

    memcpy(buff, &cluster, sizeof(SODataClust));

    if((stat = soWriteCacheCluster(nFClust, &cluster)) != 0){
      return stat;
    }
  }

  if( (stat = soStoreSuperBlock()) != 0){
    return stat;
  }

  return 0;

}
int soCleanLogicalCluster(SOSuperBlock *p_sb, uint32_t nInode, uint32_t nLClust) {

    int stat; // function return status control 
    SODataClust dc; // data cluster to be retrieved, modified and saved

    // read the data cluster, converting it's logical number to physical number
    if ((stat = soReadCacheCluster(p_sb->dZoneStart + nLClust * BLOCKS_PER_CLUSTER, &dc)) != 0)
        return stat;

    // test if the given data cluster belongs to the right inode
    if (dc.stat != nInode) return -EWGINODENB;

    //mark as clean
    dc.stat = NULL_INODE;

    // save the data cluster
    if ((stat = soWriteCacheCluster(p_sb->dZoneStart + nLClust * BLOCKS_PER_CLUSTER, &dc)) != 0)
        return stat;

    return 0;
}
Exemple #4
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;
}
Exemple #5
0
int soReplenish(SOSuperBlock *p_sb) {
    int stat, nctt, n; // stat = variavel para o estado de erro; nctt = para o numero de clusters a transmitir; n = usada nos for's
    SODataClust cluster; // ponteiro para manipulacao de um cluster
    uint32_t nLCluster, NFClt; // variavel para atribuir ao numero logico do proximo cluster a manipular, e variavel para calcular o numero fisico do bloco


    //teste de o ponteiro para o super bloco nao é NULL
    if (p_sb == NULL)
        return -EBADF;

    //teste de consistencia ao super bloco
    //if ((stat = soQCheckSuperBlock(p_sb)) != 0)
    //    return -ELIBBAD;

    // numero de clusters a transmitir, caso nao haja menos clusters livres do que a cache apenas podemos transmitir esse numero
    nctt = (p_sb->dZoneFree < DZONE_CACHE_SIZE) ? p_sb->dZoneFree : DZONE_CACHE_SIZE;
    nLCluster = p_sb->dHead; // numero logico do primeiro cluster a trasmitir encontra-se no dHead

    for (n = DZONE_CACHE_SIZE - nctt; n < DZONE_CACHE_SIZE; n++) {


        if (nLCluster == NULL_CLUSTER)
            break;

        NFClt = p_sb->dZoneStart + nLCluster * BLOCKS_PER_CLUSTER;

        //carregar o cluster nLClust usando o seu numero fisico
        if ((stat = soReadCacheCluster(NFClt, &cluster)) != 0)
            return stat;

        //inseri-lo na cache de retirada
        p_sb->dZoneRetriev.cache[n] = nLCluster;

        //avancar para o proximo cluster livre
        nLCluster = cluster.next;

        //como o cluster esta referenciado na cache de retirada do super bloco o next e prev sao NULL_CLUSTER
        cluster.prev = cluster.next = NULL_CLUSTER;


        if ((stat = soWriteCacheCluster(NFClt, &cluster)) != 0)
            return stat;
    }

    //se o for anterior nao chegou ao fim por nao haverem mais clusters livres na zona de dados, eles estao na cache de insercao
    if (n != DZONE_CACHE_SIZE) {

        p_sb->dHead = p_sb->dTail = NULL_CLUSTER;

        soDeplete(p_sb); //retirar os restantes clusters da cache de insercao

        nLCluster = p_sb->dHead;

        for (; n < DZONE_CACHE_SIZE; n++) {

            NFClt = p_sb->dZoneStart + nLCluster * BLOCKS_PER_CLUSTER;

            if ((stat = soReadCacheCluster(NFClt, &cluster)) != 0)
                return stat;

            p_sb->dZoneRetriev.cache[n] = nLCluster;
            nLCluster = cluster.next;
            cluster.prev = cluster.next = NULL_CLUSTER;

            if ((stat = soWriteCacheCluster(NFClt, &cluster)) != 0)
                return stat;

        }
    }

    //se no fim ainda houver mais clusters o proximo tem de deixar de refenciar o anterior pois ele esta na cache de retirada
    if (nLCluster != NULL_CLUSTER) {

        NFClt = p_sb->dZoneStart + nLCluster * BLOCKS_PER_CLUSTER;

        if ((stat = soReadCacheCluster(NFClt, &cluster)) != 0)
            return stat;

        cluster.prev = NULL_CLUSTER;

        if ((stat = soWriteCacheCluster(NFClt, &cluster)) != 0)
            return stat;
    }

    //actualizar o indice da cache de retirada
    p_sb->dZoneRetriev.cacheIdx = DZONE_CACHE_SIZE - nctt;

    //actualizar o dHead para o numero logico do proximo cluster livre
    p_sb->dHead = nLCluster;


    if (nLCluster == NULL_CLUSTER)
        p_sb->dTail = NULL_CLUSTER;


    //if ((stat = soStoreSuperBlock()) != 0)
    //    return stat;

    return 0;
}