Exemplo n.º 1
0
static int
remove_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);
	if(indir2_index(n)==0)
	{
		uint32_t *id2_block = ospfs_block(oi->oi_indirect2);
		uint32_t id2_off = indir_index(n);
		uint32_t *id_block = ospfs_block(id2_block[id2_off]);
		uint32_t d_off = direct_index(n);
		if(d_off == 0)//d_off == 0 means the direct is null which should make id2_block[id2_off] null
		{
			id2_block[id2_off] = NULL;
			if(id2_off == 0)
				oi->oi_indirect2 = NULL;
		}
		free_block(id_block[d_off]);
		id_block[d_off] = NULL;
	}
	else if(indir_index(n)==0)
	{
		uint32_t *id_block = ospfs_block(oi->oi_indirect);
		uint32_t d_off = direct_index(n);
		if(d_off == 0)//d_off == 0 means the direct is null which should make id2_block[id2_off] null
		{
			oi->oi_indirect = NULL;
		}
		free_block(id_block[d_off]);
		id_block[d_off] = NULL;
	}
	else
	{
		uint32_t d_off = direct_index(n);
		free_block(oi->oi_direct[d_off]);
		oi->oi_direct[d_off] = NULL;
	}
	/* EXERCISE: Your code here */
	oi->oi_size = (n-1)*OSPFS_BLKSIZE;
	return 0; // Replace this line
}
Exemplo n.º 2
0
static int
remove_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	/* EXERCISE: Your code here */
	if(n < 0) return -EIO; 
	else if(n == 0) return 0;
	
	int index = n-1;
	if(index < OSPFS_NDIRECT){
		free_block(oi->oi_direct[index]);
		oi->oi_direct[index] = 0;
	}
	else if(index < OSPFS_NDIRECT + OSPFS_NINDIRECT && index > OSPFS_NDIRECT){
		uint32_t* indirect_block = (uint32_t *)ospfs_block(oi->oi_indirect);
		free_block(indirect_block[direct_index(index)]);
		indirect_block[direct_index(index)] = 0;
		free_block(oi->oi_indirect);
		oi->oi_indirect = 0;
	}
	else if(index < OSPFS_MAXFILEBLKS){
		uint32_t * indirect2_block = (uint32_t *) ospfs_block(oi->oi_indirect2);
		uint32_t * indirect_block = (uint32_t *) ospfs_block(indirect2_block[indir_index(index)]);
		free_block(indirect_block[direct_index(index)]);
		indirect_block[direct_index(index)] = 0;
		free_block(indirect2_block[indir_index(index)]);
		indirect2_block[indir_index(index)] = 0;
		free_block(oi->oi_indirect2);
		oi->oi_indirect2 = 0;
	}
	else return -EIO;

	oi->oi_size -= OSPFS_BLKSIZE;
	return 0;
}
Exemplo n.º 3
0
static int
remove_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);
	//the nth block is the one to remove
	if (n < 0 || n > OSPFS_MAXFILEBLKS)
		return -EIO;
	if (n == 0)
		return 0;
	n--;
	//just remove n and free the block
	if (n < OSPFS_NDIRECT) {
		free_block(oi->oi_direct[n]);
		oi->oi_direct[n] = 0;
	}
	// we have single indirection
	else if (n < OSPFS_NDIRECT + OSPFS_NINDIRECT) {
		// actual indirect block in memory
		uint32_t* indirect_block = (uint32_t *) ospfs_block(oi->oi_indirect);

		// free the direct block, data block is simply unbound after freeing the direct block
		free_block(indirect_block[direct_index(n)]);
		// set the block number of n in the indirect block to 0
		indirect_block[direct_index(n)] = 0;

		// if we freed the last block indirected to, we free the indirect block and variable as well
		if (!direct_index(n)) {
			free_block(oi->oi_indirect);
			oi->oi_indirect = 0;
		}
	}
	// ugh, double indirection
	else {
		uint32_t* indirect2_block = (uint32_t *) ospfs_block(oi->oi_indirect2);
		uint32_t* indirect_block = (uint32_t *) ospfs_block(indirect2_block[indir_index(n)]);

		// free the direct block
		free_block(indirect_block[direct_index(n)]);
		indirect_block[direct_index(n)] = 0;

		if (direct_index(n) == 0) {
			free_block(indirect2_block[indir_index(n)]);
			indirect2_block[indir_index(n)] = 0;
		}
		
		if (indir_index(n) == 0) {
			free_block(oi->oi_indirect2);
			oi->oi_indirect2 = 0;
		}
	}

	oi->oi_size = oi->oi_size - OSPFS_BLKSIZE;
	return 0;
}
Exemplo n.º 4
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	// keep track of allocations to free in case of -ENOSPC
	uint32_t *allocated[2] = { 0, 0 };
	/* EXERCISE: Your code here */
	int32_t direct 	= direct_index(n);
	int32_t ind 	= indir_index(n);
	int32_t ind2 	= indir2_index(n);
	uint32_t addblock = 0;
	// case 1 - direct block
	if(ind == -1 && ind2 == -1)
	{
	  addblock = allocate_block();
	  // check alloc success
	  if(addblock == 0)
	  {
	    return -ENOSPC;
	  }
	  oi->oi_direct[n] = addblock;
	}
	// case 2 - indirect block
	else if(ind == 0 && ind2 == -1)
	{
	  return -ENOSPC;
	}
	// case 3 - indirect2 block
	else if(ind2 == 0)
	{
	  return -ENOSPC;
	}
	else
	  return -EIO; // Replace this line
	  
	oi->oi_size += OSPFS_BLKSIZE;
}
Exemplo n.º 5
0
static int
remove_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	if (n < 0)
		return -EIO;
	// no blocks to remove
	else if (n == 0)
		return 0;

	n = n - 1; // index starts at 0

	// direct block range
	if (n < OSPFS_NDIRECT) {
		// free direct block
		free_block(oi->oi_direct[n]);
		oi->oi_direct[n] = 0;
	}
	// indirect block range
	else if (n < OSPFS_NDIRECT + OSPFS_NINDIRECT) {
		uint32_t* indir = (uint32_t *) ospfs_block(oi->oi_indirect);

		// free direct block
		free_block(indir[direct_index(n)]);
		indir[direct_index(n)] = 0;

		// free indirect block if possible
		if (direct_index(n) == 0) {
			free_block(oi->oi_indirect);
			oi->oi_indirect = 0;
		}
	}
	// indirect^2 block range
	else if (n < OSPFS_MAXFILEBLKS) {
		uint32_t* indir2 = (uint32_t *) ospfs_block(oi->oi_indirect2);
		uint32_t* indir = (uint32_t *) ospfs_block(indir2[indir_index(n)]);

		// free direct block
		free_block(indir[direct_index(n)]);
		indir[direct_index(n)] = 0;

		// free indirect block if possible
		if (direct_index(n) == 0) {
			free_block(indir2[indir_index(n)]);
			indir2[indir_index(n)] = 0;
		}

		// free indirect^2 block if possible
		if (indir_index(n) == 0) {
			free_block(oi->oi_indirect2);
			oi->oi_indirect2 = 0;
		}
	}
	else
		return -EIO; // n > OSPFS_MAXFILEBLKS

	// update filesize
	oi->oi_size -= OSPFS_BLKSIZE;

	return 0;
}
Exemplo n.º 6
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	// keep track of allocations to free in case of -ENOSPC
	uint32_t allocated[2] = { 0, 0 };
	uint32_t direct, indir;

	if (n < 0)
		return -EIO;
	// direct block range
	else if (n < OSPFS_NDIRECT) {
		// allocate block
		direct = allocate_block();
		if (!direct)
			return -ENOSPC;
		memset(ospfs_block(direct), 0, OSPFS_BLKSIZE);

		// add block
		oi->oi_direct[n] = direct;
	}
	// indirect block range
	else if (n < OSPFS_NDIRECT + OSPFS_NINDIRECT) {
		// allocate new indirect block if necessary
		if (!oi->oi_indirect) {
			// allocate block
			allocated[0] = allocate_block();
			if (!allocated[0])
				return -ENOSPC;
			memset(ospfs_block(allocated[0]), 0, OSPFS_BLKSIZE);

			// set as indirect block
			oi->oi_indirect = allocated[0];
		}

		// allocate direct block
		direct = allocate_block();
		if (!direct) {
			if (allocated[0]) {
				free_block(allocated[0]);
				oi->oi_indirect = 0;
			}
			return -ENOSPC;
		}
		memset(ospfs_block(direct), 0, OSPFS_BLKSIZE);

		// add to indirect block
		((uint32_t*) ospfs_block(oi->oi_indirect))[direct_index(n)] = direct;
	}
	// indirect^2 block range
	else if (n < OSPFS_MAXFILEBLKS) {
		// allocate new indirect^2 block if necessary
		if (!oi->oi_indirect2) {
			// allocate block
			allocated[0] = allocate_block();
			if (!allocated[0])
				return -ENOSPC;
			memset(ospfs_block(allocated[0]), 0, OSPFS_BLKSIZE);

			// set as indirect^2 block
			oi->oi_indirect2 = allocated[0];
		}

		indir = ((uint32_t *) ospfs_block(oi->oi_indirect2))[indir_index(n)];

		// allocate new indirect block if necessary
		if (!indir) {
			// allocate block
			allocated[1] = allocate_block();
			if (!allocated[1]) {
				if (allocated[0])
					free_block(allocated[0]);
				return -ENOSPC;
			}
			memset(ospfs_block(allocated[1]), 0, OSPFS_BLKSIZE);

			// add to indirect^2 blocks
			indir = allocated[1];
		}

		// allocate direct block
		direct = allocate_block();
		if (!direct) {
			if (allocated[0]) {
				free_block(allocated[0]);
				oi->oi_indirect2 = 0;
			}
			if (allocated[1])
				free_block(allocated[1]);
			return -ENOSPC;
		}
		memset(ospfs_block(direct), 0, OSPFS_BLKSIZE);

		// add to indirect blocks
		((uint32_t *) ospfs_block(indir))[direct_index(n)] = direct;
	}
	else
		return -ENOSPC; // n >= OSPFS_MAXFILEBLKS

	// update filesize
	oi->oi_size += OSPFS_BLKSIZE;

	return 0;
}
Exemplo n.º 7
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);
	/*// Number of direct block pointers in 'struct ospfs_inode'.
#define OSPFS_NDIRECT		10
// Number of block pointers in an indirect block.
#define OSPFS_NINDIRECT		(OSPFS_BLKSIZE / 4)
// Maximum number of blocks in a file.
#define OSPFS_MAXFILEBLKS	*/
	// keep track of allocations to free in case of -ENOSPC
	uint32_t *allocated[2] = { 0, 0 };
	uint32_t id1, id2, d;
	/* EXERCISE: Your code here */
	if(indir2_index(n)==0)//oi_indirect2
	{
		uint32_t* id2_block = NULL;
		//which contains the table of indirect pointer
		if(oi->oi_indirect2 == NULL)
		{
			id2 = allocate_block();
			if(id2 == 0)//allocation failure
				return -ENOSPC;
			allocated[0] = id2;
			oi->oi_indirect2 = allocated[0];
			id2_block = ospfs_block(oi->oi_indirect2);
			memset(id2_block, 0, OSPFS_BLKSIZE);
		}
		else
			id2_block = ospfs_block(oi->oi_indirect2);
		uint32_t id2_off = indir_index(n);
		if(id2_block[id2_off] == NULL)
		{
			id1 = allocate_block();
			if(id1 == 0)//which means we need to erase the allocation of block of indirect
			{
				if(allocated[0])
				{
					free_block(oi->oi_indirect2);
					oi->oi_indirect2 = NULL;
				}
				return -ENOSPC;
			}
			allocated[1] = id1;
			id2_block[id2_off] = allocated[1];
		}
		//then we traverse to the direct pointer
		uint32_t *d_block = ospfs_block(id2_block[id2_off]);
		uint32_t d_off = direct_index(n);
		//check if the d_off direct pointer is valid
		if((d_block[d_off] = allocate_block()) == 0)
		{
			if(allocated[0])
			{
				free_block(allocated[0]);
				oi->oi_indirect2 = NULL;
			}
			if(allocated[1])
			{
				free_block(allocated[1]);
				id2_block[id2_off] = NULL;
			}
			return -ENOSPC;
		}
		oi->oi_size = (n+1)*OSPFS_BLKSIZE;
		return 0;
	}
	else if(indir_index(n) == 0)//if for indirect block
	{
		uint32_t *id_block;
		if(oi->oi_indirect == NULL)
		{
			id1 = allocate_block();
			if(id1 == 0)//allocation failure
				return -ENOSPC;
			allocated[0] = id1;
			oi->oi_indirect = allocated[0];
			id_block = ospfs_block(oi->oi_indirect);
			memset(id_block, 0, OSPFS_BLKSIZE);
		}
		else
			id_block = ospfs_block(oi->oi_indirect);
		uint32_t d_off = direct_index(n);
		if((id_block[d_off] = allocate_block()) == 0)
		{
			if(allocated[0])
			{
				free_block(allocated[0]);
				oi->oi_indirect = NULL;
			}
			return -ENOSPC;
		}
		oi->oi_size = (n+1)*OSPFS_BLKSIZE;
		return 0;
	}
	else
	{
		if((oi->oi_direct[n] = allocate_block()) == 0)
			return -ENOSPC;
		else
		{
			oi->oi_size = (n+1)*OSPFS_BLKSIZE;
			return 0;
		}
	//return -EIO;
	}
}
Exemplo n.º 8
0
static int
remove_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	/* EXERCISE: Your code here */
	
	//If file is empty
	if(n <= 0){
		return -EIO;	
	}

	if(indir2_index(n) == -1){
		if(indir_index(n) == -1){
			free_block(oi->oi_direct[n]);	
			oi->oi_direct[n] = 0;
		}else if(indir_index(n) == 0){
			//Indirect block should exist
			if(oi->oi_indirect <= 0){
				return -EIO;			
			}

			//Deallocate block
			uint32_t *indir_ptr = ospfs_block(oi->oi_indirect);
			free_block(indir_ptr[direct_index(n)]); 
			indir_ptr[direct_index(n)] = 0;
			
			//Deallocate indirect block if have to
			if(n == OSPFS_NDIRECT+1){
				free_block(oi->oi_indirect);
				oi->oi_indirect = 0;
			}
		}	
	}else{
		//Indirect2 block should exist
		if(oi->oi_indirect2 <= 0){
			return -EIO;		
		}
		//Deallocate block
		uint32_t *indir2_ptr = ospfs_block(oi->oi_indirect2);
		uint32_t *indir_ptr = ospfs_block(indir2_ptr[indir_index(n)]);
		free_block(indir_ptr[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT]);
		indir_ptr[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT] = 0;

		//Deallocate indirect block if have to
		if((n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT == 1){			
			free_block(indir2_ptr[indir_index(n)]);
			indir2_ptr[indir_index(n)] = 0;
		}

		//Deallocate indirect2 block if have to
		if(n == OSPFS_NDIRECT + OSPFS_NINDIRECT + 1){
			free_block(oi->oi_indirect2);
			oi->oi_indirect2 = 0;	
		}
	}

	oi->oi_size = OSPFS_BLKSIZE * (n-1);
	return 0;
}
Exemplo n.º 9
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	/* EXERCISE: Your code here */
	//Max blocks already in use
	if(n >= OSPFS_MAXFILEBLKS){
		return -ENOSPC;	
	}

	uint32_t block = allocate_block();
	if(block == 0){
		return -ENOSPC;
	}
	zero_block(block);

	//Don't need indirect2 block
	if(indir2_index(n) == -1){
			//Don't need indirect block
			if(indir_index(n) == -1){
				oi->oi_direct[n] = block;
			//Need indirect block
			}else if(indir_index(n) == 0){
				//Need to allocate new indirect block
				if(n == OSPFS_NDIRECT){
					uint32_t indir = allocate_block();
					if(indir == 0){
						free_block(block);
						return -ENOSPC;					
					}
					zero_block(indir);
					oi->oi_indirect = indir;
				}
				//Add in new block number into indirect block
				uint32_t *indir_ptr = ospfs_block(oi->oi_indirect);
				indir_ptr[direct_index(n)] = block;	
			}
	//Need indirect2 block
	}else{
		//Preset these values, so that if freed and unchanged nothing happens
		uint32_t indir = -1;
		uint32_t indir2 = -1;
		//Need to allocate new indirect2 block
		if(n == OSPFS_NDIRECT + OSPFS_NINDIRECT){
			indir2 = allocate_block();
			if(indir2 == 0){
				free_block(block);
				return -ENOSPC;			
			}
			zero_block(indir2);
			oi->oi_indirect2 = indir2;	
		}

		uint32_t *indir2_ptr = ospfs_block(oi->oi_indirect2);

		//Need to allocate new indirect block
		if((n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT == 0){
			uint32_t indir = allocate_block();
			if(indir == 0){
				free_block(block);
				free_block(indir2);
				return -ENOSPC;		
			}
			zero_block(indir);		
			indir2_ptr[indir_index(n)] = indir;
		}else{
			indir = indir2_ptr[indir_index(n)];
		}
		uint32_t *indir_ptr = ospfs_block(indir);
		indir_ptr[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT) % OSPFS_NINDIRECT] = block;
	}

	oi->oi_size = OSPFS_BLKSIZE * (n+1);
	return 0;
}
Exemplo n.º 10
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);
	// keep track of allocations to free in case of -ENOSPC
	uint32_t *allocated[2] = { 0, 0 };
	uint32_t direct, indirect;

	// direct block
	if (indir_index(n) == -1) {
		// allocate new direct block
		direct = allocate_block();
		if (!direct) return -ENOSPC;
		// zeroes the allocated block
		memset(ospfs_block(direct), 0, OSPFS_BLKSIZE);
		
		// add to oi
		oi->oi_direct[n] = direct;
	}
	// singly indirect
	else if ((indir_index(n) == 0) && (indir2_index(n) == -1)) {
		// first time allocating indirect block
		// add oi->oi_indirect
		if (direct_index(n) == 0) {
			allocated[0] = allocate_block();
			if (!allocated[0]) return -ENOSPC;
			// zeroes the allocated array
			memset(ospfs_block(allocated[0]), 0, OSPFS_BLKSIZE);
			oi->oi_indirect = allocated[0];
		}

		// create block
		direct = allocate_block();
		if (!direct) {
			free_block(allocated[0]);
			free_block(direct);
			oi->oi_indirect = 0;
			return -ENOSPC;
		}
		// zeroes the allocated array
		memset(ospfs_block(direct), 0, OSPFS_BLKSIZE);

		// add to oi
		((uint32_t*) ospfs_block(oi->oi_indirect))[direct_index(n)] = direct;
	}
	// double indirection
	else {
		// first time doing double indirection
		if (n == (OSPFS_NINDIRECT + OSPFS_NDIRECT)) {
			allocated[0] = allocate_block();
			if (!allocated[0]) return -ENOSPC;
			// zeroes the allocated array
			memset(ospfs_block(allocated[0]), 0, OSPFS_BLKSIZE);
			oi->oi_indirect2 = allocated[0];
		}

		// allocate new indirect block if necessary
		if (direct_index(n) == 0) {
			allocated[1] = allocate_block();
			if (!allocated[1]) {
				// free previously allocated double indirect block
				if (allocated[0]) {
					free_block(allocated[0]);
					oi->oi_indirect2 = 0;
				}
				return -ENOSPC;
			}
			// zeroes the allocated array
			memset(ospfs_block(allocated[1]), 0, OSPFS_BLKSIZE);
		}

		// create block
		direct = allocate_block();
		if (!direct) {
			// if we allocated double indirect block
			if (!allocated[0]) {
				free_block(allocated[0]);
				free_block(allocated[1]);
				oi->oi_indirect2 = 0;
				return -ENOSPC;
			}
			// if we only allocated a single indirect block
			if (!allocated[1]) {
				free_block(allocated[1]);
			}
		}
		memset(ospfs_block(direct), 0, OSPFS_BLKSIZE);

		// add to oi
		((uint32_t*) ospfs_block(oi->oi_indirect2))[indir_index(n)] = allocated[1];
		((uint32_t*) ((uint32_t*) ospfs_block(oi->oi_indirect2))[indir_index(n)])[direct_index(n)] = direct;
	}

	oi->oi_size = oi->oi_size + OSPFS_BLKSIZE;
	return 0;
	/* DONE: Your code here */
}
Exemplo n.º 11
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);			

	// keep track of allocations to free in case of -ENOSPC
	uint32_t allocated[2] = { 0, 0 };
	
	/* EXERCISE: Your code here */
	if (n == OSPFS_MAXFILEBLKS)
		return -ENOSPC;
	allocated[0] = allocate_block();
	if (allocated[0] == 0)
		return -ENOSPC;
	memset(ospfs_block(allocated[0]), 0, OSPFS_BLKSIZE);

	if (n < OSPFS_NDIRECT) {
		oi->oi_direct[n] = allocated[0];
	} else {
		uint32_t *indirect_block;

		// allocate indirect block if necessary
		if (direct_index(n) == 0) {
			allocated[1] = allocate_block();
			if (allocated[1] == 0) {
				free_block(allocated[0]);
				return -ENOSPC;
			}
			memset(ospfs_block(allocated[1]), 0, OSPFS_BLKSIZE);

			// update inode the first time
			if (n == OSPFS_NDIRECT)
				oi->oi_indirect = allocated[1];
		}

		// link to direct block
		if (n < OSPFS_NDIRECT + OSPFS_NINDIRECT) {
			indirect_block = ospfs_block(oi->oi_indirect);
			indirect_block[n - OSPFS_NDIRECT] = allocated[0]; 
		} else {
			uint32_t blockoff = n - (OSPFS_NDIRECT + OSPFS_NINDIRECT);
			uint32_t *indirect2_block;
			uint32_t *indirect_block;
			
			if (n == OSPFS_NDIRECT + OSPFS_NINDIRECT) {
				oi->oi_indirect2 = allocate_block();
				if (oi->oi_indirect2 == 0) {
					free_block(allocated[0]);
					free_block(allocated[1]);
					return -ENOSPC;
				}
				memset(ospfs_block(oi->oi_indirect2), 0, OSPFS_BLKSIZE);
			}
			indirect2_block = ospfs_block(oi->oi_indirect2);
			if (allocated[1] != 0)
				indirect2_block[blockoff / OSPFS_NINDIRECT] = allocated[1];
			indirect_block = ospfs_block(indirect2_block[blockoff / OSPFS_NINDIRECT]);
			indirect_block[blockoff % OSPFS_NINDIRECT] = allocated[0];
		}
	}
	oi->oi_size += OSPFS_BLKSIZE;
	return 0; 
}
Exemplo n.º 12
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);

	// keep track of allocations to free in case of -ENOSPC
	uint32_t allocated[2] = { 0, 0 };

	uint32_t direct_block, indirect_block;
	/* EXERCISE: Your code here */
	if(n < 0) return -EIO;
	else if(n < OSPFS_NDIRECT){ //direct block domain
		direct_block = allocate_block();
		if(!direct_block) return -ENOSPC;
		memset(ospfs_block(direct_block), 0, OSPFS_BLKSIZE);
		oi->oi_direct[n] = direct_block;	
	}
	else if(n < OSPFS_NDIRECT + OSPFS_NINDIRECT){//indirect block domain
		if(!oi->oi_indirect){ //allocate a new indirect block 
			allocated[0] = allocate_block();
			if(!allocated[0]) return -ENOSPC;
			memset(ospfs_block(allocated[0]), 0, OSPFS_BLKSIZE);
			oi->oi_indirect = allocated[0];
		}
		direct_block = allocate_block();
		if(!direct_block){
			oi->oi_indirect = 0;
			free_block(allocated[0]);
			return -ENOSPC;
		}
		memset(ospfs_block(direct_block),0, OSPFS_BLKSIZE);
		((uint32_t *)ospfs_block(oi->oi_indirect))[direct_index(n)] = direct_block;
	}
	else if(n > OSPFS_NDIRECT + OSPFS_NINDIRECT && n < OSPFS_MAXFILEBLKS){ // double indirect domain
		if(!oi->oi_indirect2){
			allocated[1] = allocate_block();
			if(!allocated[1]) return -ENOSPC; 
			memset(ospfs_block(allocated[1]), 0, OSPFS_BLKSIZE);
			oi->oi_indirect2 = allocated[1];
		}
		indirect_block = ((uint32_t *) ospfs_block(oi->oi_indirect2))[indir_index(n)];
		if(!indirect_block){
			allocated[0] = allocate_block();
			if(!allocated[0]){
				free_block(allocated[1]);
				return -ENOSPC;
			}
			memset(ospfs_block(allocated[0]),0, OSPFS_BLKSIZE);
			indirect_block = allocated[0];	
		}
		direct_block = allocate_block();
		if(!direct_block){
			free_block(allocated[0]);
			free_block(allocated[1]);
			oi->oi_indirect2 = 0;
			return -ENOSPC;
		}
		memset(ospfs_block(direct_block),0,OSPFS_BLKSIZE);
		((uint32_t*) ospfs_block(indirect_block))[direct_index(n)] = direct_block;
	}
	else return -ENOSPC;

	oi->oi_size += OSPFS_BLKSIZE;
	return 0;
}