Exemple #1
0
int testfs_free_blocks(struct inode *in) {
    int i;
    int e_block_nr;

    /* last block number */
    e_block_nr = DIVROUNDUP(in->in.i_size, BLOCK_SIZE);

    /* remove direct blocks */
    for (i = 0; i < e_block_nr && i < NR_DIRECT_BLOCKS; i++) {
        if (in->in.i_block_nr[i] == 0)
            continue;
        testfs_free_block_from_inode(in, in->in.i_block_nr[i]);
        in->in.i_block_nr[i] = 0;
    }
    e_block_nr -= NR_DIRECT_BLOCKS;

    /* remove indirect blocks */
    if (in->in.i_indirect > 0) {
        char block[BLOCK_SIZE];
        read_blocks(in->sb, block, in->in.i_indirect, 1);
        for (i = 0; i < e_block_nr && i < NR_INDIRECT_BLOCKS; i++) {
            testfs_free_block_from_inode(in, ((int *) block)[i]);
            ((int *) block)[i] = 0;
        }
        testfs_free_block_from_inode(in, in->in.i_indirect);
        in->in.i_indirect = 0;
    }

    e_block_nr -= NR_INDIRECT_BLOCKS;
    if (e_block_nr >= 0) {
        int j = 0;
        int deleted = 0;
        char block[BLOCK_SIZE];
        read_blocks(in->sb, block, in->in.i_dindirect, 1);
        for(i = 0; deleted < e_block_nr && i < NR_INDIRECT_BLOCKS; i++){
            if(((int *)block)[i] > 0){
                char single_block[BLOCK_SIZE];
                read_blocks(in->sb, single_block, ((int *)block)[i], 1);
                for(j = 0; deleted < e_block_nr && j < NR_INDIRECT_BLOCKS; j++){
                    testfs_free_block_from_inode(in, ((int *) single_block)[j]);
                    ((int *) single_block)[j] = 0;
                    deleted++;
                }
                testfs_free_block_from_inode(in, ((int *) block)[i]);
                ((int *) block)[i] = 0;
            } else
                deleted += NR_INDIRECT_BLOCKS;
        }
        testfs_free_block_from_inode(in, in->in.i_dindirect);
        in->in.i_dindirect = 0;
    }

    in->in.i_size = 0;
    in->i_flags |= I_FLAGS_DIRTY;
    return 0;
}
/* given logical block number, allocate a new physical block, if it does not
 * exist already, and return the physical block number that is allocated.
 * returns negative value on error. */
 static int
 testfs_allocate_block(struct inode *in, int log_block_nr, char *block)
 {
 	if (log_block_nr>4196361)
 		return -EFBIG;
 	// //printf("log_block_nr:%d\n",log_block_nr);
 	// }

 	int phy_block_nr;
 	char indirect[BLOCK_SIZE];
 	char dindirect[BLOCK_SIZE];
 	char dindirect2[BLOCK_SIZE];
 	int indirect_allocated = 0;
 	//int dindirect_allocated = 0;
 	
 	assert(log_block_nr >= 0);
 	phy_block_nr = testfs_read_block(in, log_block_nr, block);

	/* phy_block_nr > 0: block exists, so we don't need to allocate it, 
	   phy_block_nr < 0: some error */
 	if (phy_block_nr != 0)
 		return phy_block_nr;

	/* allocate a direct block */
 	if (log_block_nr < NR_DIRECT_BLOCKS) {
 		assert(in->in.i_block_nr[log_block_nr] == 0);
 		phy_block_nr = testfs_alloc_block_for_inode(in);
 		if (phy_block_nr >= 0) {
 			in->in.i_block_nr[log_block_nr] = phy_block_nr;
 		}
 		return phy_block_nr;
 	}

 	log_block_nr -= NR_DIRECT_BLOCKS;

 	if (log_block_nr >= NR_INDIRECT_BLOCKS)
 	{
 	
 		log_block_nr -= NR_INDIRECT_BLOCKS; //log block ranges from 0 ~ 4194303
 		
 		int level1_block = DIVROUNDUP(log_block_nr+1,2048) - 1;   // ranges 0~2047
 		
 		int level2_block= log_block_nr % 2048;

 		/* allocate an dindirect block */
 		if (in->in.i_dindirect == 0) 	
 		{	
 			bzero(dindirect, BLOCK_SIZE);
 			phy_block_nr = testfs_alloc_block_for_inode(in);
 			if (phy_block_nr < 0)
 				return phy_block_nr;
 			//dindirect_allocated = 1;
 			in->in.i_dindirect = phy_block_nr;
 			//printf("dindirect block #:%d\n",phy_block_nr);
 		}

 		else   /* read dindirect block */
 		{
 			read_blocks(in->sb, dindirect, in->in.i_dindirect, 1); 
 		}



 		// Allocate 2nd level indirect block
 		if (((int *)dindirect)[level1_block] == 0)
 		{
 			bzero(dindirect2, BLOCK_SIZE);
 			phy_block_nr = testfs_alloc_block_for_inode(in);
 			if (phy_block_nr < 0)
 				return phy_block_nr;
 			((int*)dindirect)[level1_block]=phy_block_nr;
	 		//printf("2nd dindirect block #:%d\n", ((int*)dindirect)[level1_block]);
 			write_blocks(in->sb, dindirect, in->in.i_dindirect,1);
 		}

 		// error here....
 		// Read 2nd level indirect block
 		else 
 		{	
 			read_blocks(in->sb, dindirect2, ((int*)dindirect)[level1_block], 1);
 		}


 		// allocate direct block */
 		phy_block_nr=testfs_alloc_block_for_inode(in);


	 	if (phy_block_nr >=0)  // update 2nd level indirect block
	 	{
	 		((int*)dindirect2)[level2_block]=phy_block_nr;
	 		//printf("Last direct block #:%d\n", ((int*)dindirect2)[level2_block]);
	 		write_blocks(in->sb, dindirect2, ((int*)dindirect)[level1_block], 1);
	 	}
	 	
	 	return phy_block_nr;
 		// Allocate 2nd-level indirect block

	 }

 	/**** Allocating in 1st level indirect blocks ****/

	if (in->in.i_indirect == 0) 	/* allocate an indirect block */
	 {	
	 	bzero(indirect, BLOCK_SIZE);
	 	phy_block_nr = testfs_alloc_block_for_inode(in);
	 	if (phy_block_nr < 0)
	 		return phy_block_nr;
	 	indirect_allocated = 1;
	 	in->in.i_indirect = phy_block_nr;
	 } 

	 else 
	{	/* read indirect block */
	 	read_blocks(in->sb, indirect, in->in.i_indirect, 1);
	}

	/* allocate direct block */
	assert(((int *)indirect)[log_block_nr] == 0);	
	phy_block_nr = testfs_alloc_block_for_inode(in);

	if (phy_block_nr >= 0) {
		/* update indirect block */
		((int *)indirect)[log_block_nr] = phy_block_nr;
		write_blocks(in->sb, indirect, in->in.i_indirect, 1);
	} 

	else if (indirect_allocated) 
	{
		/* free the indirect block that was allocated */
		testfs_free_block_from_inode(in, in->in.i_indirect);
	}

	return phy_block_nr;

}
Exemple #3
0
/* given logical block number, allocate a new physical block, if it does not
 * exist already, and return the physical block number that is allocated.
 * returns negative value on error. */
static int testfs_allocate_block(struct inode *in, int log_block_nr, char *block) {
    int phy_block_nr;
    char indirect[BLOCK_SIZE];
    int indirect_allocated = 0;

    assert(log_block_nr >= 0);
    phy_block_nr = testfs_read_block(in, log_block_nr, block);

    /* phy_block_nr > 0: block exists, so we don't need to allocate it, 
       phy_block_nr < 0: some error */
    if (phy_block_nr != 0)
        return phy_block_nr;

    /* allocate a direct block */
    if (log_block_nr < NR_DIRECT_BLOCKS) {
        assert(in->in.i_block_nr[log_block_nr] == 0);
        phy_block_nr = testfs_alloc_block_for_inode(in);
        if (phy_block_nr >= 0) {
            in->in.i_block_nr[log_block_nr] = phy_block_nr;
        }
        return phy_block_nr;
    }

    log_block_nr -= NR_DIRECT_BLOCKS;
    if (log_block_nr >= NR_INDIRECT_BLOCKS) {
        log_block_nr -= NR_INDIRECT_BLOCKS;
        char dindirect[BLOCK_SIZE];
        int dindirect_allocated = 0;
        int position = log_block_nr/NR_INDIRECT_BLOCKS;
        if (log_block_nr >= NR_INDIRECT_BLOCKS * NR_INDIRECT_BLOCKS) {
            return -EFBIG;
        }
        //get the double indirect block first
        if(in->in.i_dindirect == 0){
            bzero(dindirect, BLOCK_SIZE);
            phy_block_nr = testfs_alloc_block_for_inode(in);
            if(phy_block_nr < 0)
                return phy_block_nr;
            dindirect_allocated = 1;
            in->in.i_dindirect = phy_block_nr;
        } else{
            read_blocks(in->sb, dindirect, in->in.i_dindirect, 1);
        }
        //get the indirect block in double indirect block
        if(((int*) dindirect)[position] == 0) {
            bzero(indirect, BLOCK_SIZE);
            phy_block_nr = testfs_alloc_block_for_inode(in);
            if (phy_block_nr < 0){
                if (dindirect_allocated) {
                    testfs_free_block_from_inode(in, in->in.i_dindirect);
                    return phy_block_nr;
                }
            } else{
                indirect_allocated = 1;
                ((int *) dindirect)[position] = phy_block_nr;
                write_blocks(in->sb, dindirect, in->in.i_dindirect, 1);
            }
        }else{
            read_blocks(in->sb, indirect, ((int*) dindirect)[position], 1);
        }
        //get the direct block
        assert(((int *) indirect)[log_block_nr % NR_INDIRECT_BLOCKS] == 0);
        phy_block_nr = testfs_alloc_block_for_inode(in);
        if(phy_block_nr < 0){
            if(dindirect_allocated){
                testfs_free_block_from_inode(in, ((int *)dindirect)[position]);
                testfs_free_block_from_inode(in, in->in.i_dindirect);
            }else if(indirect_allocated)
                testfs_free_block_from_inode(in, ((int *)dindirect)[position]);
            return phy_block_nr;
        }
        else if (phy_block_nr >= 0) {
            ((int *) indirect)[log_block_nr % NR_INDIRECT_BLOCKS] = phy_block_nr;
            write_blocks(in->sb, indirect, ((int *)dindirect)[position], 1);
        } 
        return phy_block_nr;
    } 
    
    
    if (in->in.i_indirect == 0) { /* allocate an indirect block */
        bzero(indirect, BLOCK_SIZE);
        phy_block_nr = testfs_alloc_block_for_inode(in);
        if (phy_block_nr < 0)
            return phy_block_nr;
        indirect_allocated = 1;
        in->in.i_indirect = phy_block_nr;
    } else { /* read indirect block */
        read_blocks(in->sb, indirect, in->in.i_indirect, 1);
    }

    /* allocate direct block */
    assert(((int *) indirect)[log_block_nr] == 0);
    phy_block_nr = testfs_alloc_block_for_inode(in);

    if (phy_block_nr >= 0) {
        /* update indirect block */
        ((int *) indirect)[log_block_nr] = phy_block_nr;
        write_blocks(in->sb, indirect, in->in.i_indirect, 1);
    } else if (indirect_allocated) {
        /* free the indirect block that was allocated */
        testfs_free_block_from_inode(in, in->in.i_indirect);
    }
    return phy_block_nr;
}