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; }
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 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; }