Пример #1
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;

	while (ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size))
{
        	/* EXERCISE: Your code here */

    	r = add_block(oi);
    	if(r<0)
        	return r;
	}
	while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size))
{
        	/* EXERCISE: Your code here */
    	r = remove_block(oi);
    	if(r<0)
        	return r;
	}

	/* EXERCISE: Make sure you update necessary file meta data
             	and return the proper value. */
	oi->oi_size = new_size;
	return r;

}
Пример #2
0
static int
remove_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);
	uint32_t block_no = 0;
	uint32_t *ptr;

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

	/* EXERCISE: Your code here */
	if (0 < n && n <= OSPFS_NDIRECT) {
		oi->oi_direct[n - 1] = 0;
		free_block(n - 1);
		goto out;
	}

	// The block to be allocated has to be in indirect or indirect2
	n -= OSPFS_NDIRECT;
	if (0 < n && n <= OSPFS_NINDIRECT) {
		if (oi->oi_indirect) {
			ptr = ospfs_block(oi->oi_indirect);
			free_block(ptr[n - 1]);
			ptr[n - 1] = 0;
			if ((n - 1) == 0) {
				free_block(oi->oi_indirect);
				oi->oi_indirect = 0;
			}
		}
		goto out;
	}

	// next block must lie in indirect2
	n -= OSPFS_NINDIRECT;
	if (0 < n && n <= (OSPFS_NINDIRECT * OSPFS_NINDIRECT)) {
		uint32_t *ptrl1, *ptrl2;
		uint32_t level1 = (n - 1) / OSPFS_NINDIRECT;
		uint32_t level2 = (n - 1) % OSPFS_NINDIRECT;

		ptrl1 = ospfs_block(oi->oi_indirect2);
		ptrl2 = ospfs_block(ptrl1[level1]);
		if (ptrl2[level2]) {
			free_block(ptrl2[level2]);
			ptrl2[level2] = 0;
		}
		if (level2 == 0) {
			free_block(ptrl1[level1]);
			ptrl1[level1] = 0;
			if (level1 == 0) {
				free_block(oi->oi_indirect2);
				oi->oi_indirect2 = 0;
			}
		}
	}
 out:
	return 0;
}
Пример #3
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 */
	return -EIO; // Replace this line
}
Пример #4
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;
}
Пример #5
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;
	//grow the block
	while (ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size)) {
	    add_block(oi);

	        /* EXERCISE: Your code here */
		return -EIO; // Replace this line
	}
	while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size)) {
	        /* EXERCISE: Your code here */
		return -EIO; // Replace this line
	}

	/* EXERCISE: Make sure you update necessary file meta data
	             and return the proper value. */
	return -EIO; // Replace this line
}
Пример #6
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;

	while (ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size)) {
		r = add_block(oi);
		if (r == -ENOSPC) {
			while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(old_size)) {
				remove_block(oi);
			}
			oi->oi_size = old_size;
			return r;
		}
		else if (r == -EIO) {
			return r;
		}
	        /* DONE: Your code here */
	}
	while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size)) {
		r = remove_block(oi);
		if (r < 0) {
			return r;
		}
	        /* DONE: Your code here */
	}
	
	oi->oi_size = new_size;
	return 0;
	/* DONE: Make sure you update necessary file meta data
	             and return the proper value. */
}
Пример #7
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;

	// grow
	while (ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size)) {
		r = add_block(oi);
		if (r < 0)
			break;
	}

	if (r == -EIO)
		return -EIO;
	else if (r == -ENOSPC) {
		// shrink back to old size
		while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(old_size))
			r = remove_block(oi);

		oi->oi_size = old_size;
		return -ENOSPC;
	}

	while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size)) {
		r = remove_block(oi);
		if (r < 0)
			return r;
	}

	// update to exact size
	oi->oi_size = new_size;

	return 0;
}
Пример #8
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;

	/* EXERCISE: Your code here */
	//Grow file
	//eprintk("size:%d, size2: %d\n", oi->oi_size, new_size);
	if(ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size)){
		while (ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size) && r >= 0){
			r = add_block(oi);
		}
		//Shrink file back to original if there is an error
		if(r < 0){
			//Only shrink till old_size + the blocksize - 1, avoids the extra time when add
			//rounds up 
			while(ospfs_size2nblocks(oi->oi_size) > old_size + OSPFS_BLKSIZE - 1){
				remove_block(oi);			
			}
			oi->oi_size = old_size;
			return r;
		}

		//Subtract excess size if add rounded up
		oi->oi_size -= OSPFS_BLKSIZE - old_size % OSPFS_BLKSIZE; 
	//Shrink file
	}else if(ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size)){
		while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size) && r >= 0) {
			r = remove_block(oi);
		}

		//If error return error and exit
		if(r < 0)
			return r;
	}	
	oi->oi_size = new_size;
	return 0;
}
Пример #9
0
static void
free_block(uint32_t blockno)
{
  
  	unsigned* bitmap = &ospfs_data[OSPFS_FREEMAP_BLK];
	//unsigned size_of_bitmap_bits = (ospfs_super->os_nblocks);
	unsigned nblocks_in_bitmap = ospfs_size2nblocks((ospfs_super->os_nblocks)/8);

	/* EXERCISE: Your code here */

	if((blockno <= OSPFS_FREEMAP_BLK + nblocks_in_bitmap) || (blockno >= ospfs_super->os_nblocks)) {
		//do nothing
		return;
	} else {
		bitvector_set(bitmap, blockno);
	}
}
Пример #10
0
int
mark_inode_bitmap(ospfs_inode_t *oi, uint8_t *bitmap)
{
	int i, j;
	uint32_t *ptrl1, *ptrl2;
	int next_block = ospfs_size2nblocks(oi->oi_size);

	if (next_block == 0) {
		return 0;
	}

	for (i = 0; (i < OSPFS_NDIRECT) && oi->oi_direct[i]; i++) {
		bitvector_clear(bitmap, oi->oi_direct[i]);
	}

	if (i < OSPFS_NDIRECT || !oi->oi_indirect) {
		return 0;
	}

	next_block -= OSPFS_NDIRECT;
	bitvector_clear(bitmap, oi->oi_indirect);
	ptrl1 = ospfs_block(oi->oi_indirect);
	for (i = 0; i < OSPFS_NINDIRECT && ptrl1[i]; i++) {
		bitvector_clear(bitmap, ptrl1[i]);
	}

	if (i < OSPFS_NINDIRECT || !oi->oi_indirect2) {
		return 0;
	}

	next_block -= OSPFS_NINDIRECT;
	bitvector_clear(bitmap, oi->oi_indirect2);
	ptrl1 = ospfs_block(oi->oi_indirect);
	for (i = 0; i < OSPFS_NINDIRECT && ptrl1[i]; i++) {
		ptrl2 = ospfs_block(ptrl1[i]);
		bitvector_clear(bitmap, ptrl1[i]);
		for (j = 0; j < OSPFS_NINDIRECT && ptrl2[j]; j++) {
			bitvector_clear(bitmap, ptrl2[j]);
		}
		if (j < OSPFS_NINDIRECT) {
			break;
		}
	}

	return 0;
}
Пример #11
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 */
	uint32_t blockno = n - 1;
	if (blockno >= OSPFS_NDIRECT + OSPFS_NINDIRECT) {
		uint32_t blockoff = blockno - (OSPFS_NDIRECT + OSPFS_NINDIRECT);
		uint32_t *indirect2_block;
		uint32_t *indirect_block;
		if (oi->oi_indirect2 == 0)
			return -EIO;
		indirect2_block = ospfs_block(oi->oi_indirect2);
		if (indirect2_block[blockoff / OSPFS_NINDIRECT] == 0)
			return -EIO;
		indirect_block = ospfs_block(indirect2_block[blockoff / OSPFS_NINDIRECT]);

		free_block(indirect_block[blockoff % OSPFS_NINDIRECT]);
		indirect_block[blockoff % OSPFS_NINDIRECT] = 0;
		if (blockoff % OSPFS_NINDIRECT == 0) {
			free_block(indirect2_block[blockoff / OSPFS_NINDIRECT]);
			indirect2_block[blockoff / OSPFS_NINDIRECT] = 0;
			if (blockno == OSPFS_NDIRECT + OSPFS_NINDIRECT) {
				free_block(oi->oi_indirect2);
				oi->oi_indirect2 = 0;
			}
		}
	} else if (blockno >= OSPFS_NDIRECT) {
		uint32_t *indirect_block = ospfs_block(oi->oi_indirect);
		if (oi->oi_indirect == 0)
			return -EIO;

		free_block(indirect_block[blockno - OSPFS_NINDIRECT]);
		if (blockno - OSPFS_NDIRECT == 0)
			free_block(oi->oi_indirect);
	} else {
		free_block(oi->oi_direct[blockno]);
		oi->oi_direct[blockno] = 0;
	}
	oi->oi_size -= OSPFS_BLKSIZE;
	return 0; 
}
Пример #12
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
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
0
static int
remove_block(ospfs_inode_t *oi)
{
 // current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size) - 1;

/* EXERCISE: Your code here */
	//3 cases: below OSPFS_NDIRECT, below OSPFS_NDIRECT+OSPFS_NINDIRECT, below OSPFS_NDIRECT+OSPFS_NINDRECT+OSPFS_NINDIRECT^2
	uint32_t* block;
	if(n <= OSPFS_NDIRECT)
		free_block(oi->oi_direct[n]);

	else if(n <= (OSPFS_NDIRECT + OSPFS_NINDIRECT))
	{
		block = ospfs_block(oi->oi_indirect);
		free_block(block[n-OSPFS_NDIRECT]);
		if(n == OSPFS_NDIRECT+1)
			free_block(oi->oi_indirect);
	}
	else if(n <= (OSPFS_NINDIRECT + OSPFS_NDIRECT + (OSPFS_NINDIRECT*OSPFS_NINDIRECT)))
	{
		block = ospfs_block(oi->oi_indirect2);

	//edge cases:
		if ((n-OSPFS_NDIRECT-OSPFS_NINDIRECT)%OSPFS_NINDIRECT == 0)
			free_block(block[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT)%OSPFS_NINDIRECT]);
		if ((n-OSPFS_NDIRECT-OSPFS_NINDIRECT)/OSPFS_NINDIRECT == 0)
			free_block(block[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT)/OSPFS_NINDIRECT]);
		//otherwise:
		free_block(oi->oi_indirect2);
	}
	else
		return -EIO;
	
	oi->oi_size = n * OSPFS_BLKSIZE;
	return 0;
}
Пример #16
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;

	while (ospfs_size2nblocks(oi->oi_size) < ospfs_size2nblocks(new_size)) {
	        /* EXERCISE: Your code here SQ */
		 r = add_block(oi);
		 if (r = -ENOSPC)
		 {
			//remove blocks until old size
			while(ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(old_size))
			{
				r = remove_block(oi);
				if( r< 0)
					return -EIO;
			}
			oi->oi_size = old_size;
			return -ENOSPC;
		 } else if (r = -EIO) {
			return r;
		 }
	}
	while (ospfs_size2nblocks(oi->oi_size) > ospfs_size2nblocks(new_size)) {
	        /* EXERCISE: Your code here */
		 r = remove_block(oi);
		 if (r = -EIO)
			return r;
	}

	/* EXERCISE: Make sure you update necessary file meta data
	             and return the proper value. */
	 oi->oi_size = new_size;
	 
	 return 0;
}
Пример #17
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;
}
Пример #18
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;
}
Пример #19
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;
}
Пример #20
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; 
}
Пример #21
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;
	}
}
Пример #22
0
static int
add_block(ospfs_inode_t *oi)
{
	// current number of blocks in file
	uint32_t n = ospfs_size2nblocks(oi->oi_size);
	int32_t next_block = n + 1;
	int32_t retval = -ENOSPC;
	uint32_t block_no = 0;
	uint32_t *ptr;

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

	/* EXERCISE: Your code here */
	if (0 < next_block && next_block <= OSPFS_NDIRECT) {
		if (_add_block(&oi->oi_direct[next_block - 1])) {
			retval = 0;
		}
		goto out;
	}

	// The block to be allocated has to be in indirect or indirect2
	next_block -= OSPFS_NDIRECT;
	if (0 < next_block && next_block <= OSPFS_NINDIRECT) {
		if (!oi->oi_indirect) {
			if (!(allocated[0] = _add_block(&oi->oi_indirect))) {
				goto out;
			}
		}

		ptr = ospfs_block(oi->oi_indirect);
		if (!_add_block(&ptr[next_block - 1])) {
			if (allocated[0]) {
				free_block(allocated[0]);
				oi->oi_indirect = 0;
			}
			goto out;
		}
		retval = 0;
		goto out;
	}

	// next block must lie in indirect2
	next_block -= OSPFS_NINDIRECT;
	if (0 < next_block && next_block <= (OSPFS_NINDIRECT * OSPFS_NINDIRECT)) {
		uint32_t *ptrl1, *ptrl2;
		uint32_t level1 = (next_block - 1) / OSPFS_NINDIRECT;
		uint32_t level2 = (next_block - 1) % OSPFS_NINDIRECT;
		if (!oi->oi_indirect2) {
			if (!(allocated[0] = _add_block(&oi->oi_indirect2))) {
				goto out;
			}
		}

		ptrl1 = ospfs_block(oi->oi_indirect2);
		if (!ptrl1[level1]) {
			if (!(allocated[1] = _add_block(&ptrl1[level1]))) {
				if (allocated[0]) {
					free_block(allocated[0]);
					oi->oi_indirect2 = 0;
				}
				goto out;
			}
		}

		ptrl2 = ospfs_block(ptrl1[level1]);
		if (!ptr[level2]) {
			if (!_add_block(&ptr[level2])) {
				if (allocated[0]) {
					free_block(allocated[0]);
					oi->oi_indirect2 = 0;
				}
				if (allocated[1]) {
					free_block(allocated[1]);
					((uint32_t *) ospfs_block(allocated[1]))
						[level1] = 0;
				}
				goto out;
			}
			retval = 0;
			goto out;
		}	
	}
 out:
	return retval;
}
Пример #23
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;
}
Пример #24
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;
}
Пример #25
0
static int
change_size(ospfs_inode_t *oi, uint32_t new_size)
{
	uint32_t old_size = oi->oi_size;
	int r = 0;

	/* EXERCISE: Your code here */
	if (ospfs_size2nblocks(old_size) < ospfs_size2nblocks(new_size)) {
		while (ospfs_size2nblocks(oi->oi_size) <
		       ospfs_size2nblocks(new_size)) {
			if ((r = add_block(oi))) {
				break;
			}
			oi->oi_size = (ospfs_size2nblocks(oi->oi_size) + 1) *
				OSPFS_BLKSIZE;
		}
		if (ospfs_size2nblocks(oi->oi_size) ==
		    ospfs_size2nblocks(new_size)) {
			oi->oi_size = new_size;
			goto out;
		}
		while (ospfs_size2nblocks(old_size) !=
		       ospfs_size2nblocks(oi->oi_size)) {
			remove_block(oi);
			oi->oi_size = (ospfs_size2nblocks(oi->oi_size) - 1) *
				OSPFS_BLKSIZE;
		}
		oi->oi_size = old_size;
	} else if (ospfs_size2nblocks(old_size) > ospfs_size2nblocks(new_size)) {
		while (ospfs_size2nblocks(oi->oi_size) >
		       ospfs_size2nblocks(new_size)) {
			/* EXERCISE: Your code here */
			remove_block(oi);
			oi->oi_size = (ospfs_size2nblocks(oi->oi_size) - 1) *
				OSPFS_BLKSIZE;
		}
		oi->oi_size = new_size;
	} else {
		oi->oi_size = new_size;
	}
 out:
	return r;
}
Пример #26
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 */
}
Пример #27
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 blocknum;
	uint32_t* newblock;
	//3 cases: below OSPFS_NDIRECT, below OSPFS_NDIRECT+OSPFS_NINDIRECT, below OSPFS_NDIRECT+OSPFS_NINDRECT+OSPFS_NINDIRECT^2
    blocknum = allocate_block();
	if (n < OSPFS_NDIRECT) {
    	if (blocknum)
        	oi->oi_direct[n] = blocknum;
    	else
        	return -ENOSPC;
	}
	else if (n < OSPFS_NDIRECT+OSPFS_NINDIRECT) {
    	blocknum = allocate_block();
    	if (OSPFS_NDIRECT == n) {
        	if (blocknum) {
            	allocated[0] = blocknum;
            	oi->oi_indirect = blocknum;
        	}
        	else
            	return -ENOSPC;
    	}
    	else if (blocknum == 0) {
        	if (allocated[0])
            	free_block(allocated[0]);
        	return -ENOSPC;
    	}
    	newblock = ospfs_block(oi->oi_indirect);
    	newblock[n-OSPFS_NDIRECT] = blocknum;
	}

	else if (n < OSPFS_NDIRECT + OSPFS_NINDIRECT + OSPFS_NINDIRECT*OSPFS_NINDIRECT)
	{
    	if (n == OSPFS_NDIRECT+OSPFS_NINDIRECT)
    	{
        	if (blocknum)
        	{
            	allocated[0] = blocknum;
            	oi->oi_indirect2 = blocknum;
        	}
        	else    
            	return -ENOSPC;
    	}
    	else if ((n-OSPFS_NDIRECT - OSPFS_NINDIRECT) % OSPFS_NINDIRECT==0)
    	{
        	if (blocknum)
        	{
				uint32_t index = (n - OSPFS_NDIRECT - OSPFS_NINDIRECT)/OSPFS_NINDIRECT;
				newblock = ospfs_block(oi->oi_indirect2);
				newblock[index] = blocknum;
				allocated[1] = blocknum;
        	}
        	else
        	{
				if(allocated[0])
					free_block(allocated[0]);
				return -ENOSPC;
        	}
    	}
    	if (blocknum == 0) {
        	if (allocated[0]) 
				free_block(allocated[0]);
        	if (allocated[1]) 
				free_block(allocated[1]);
        	return -ENOSPC;
    	}
    	newblock = ospfs_block(oi->oi_indirect2);

    uint32_t* index = ospfs_block(newblock[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT)/OSPFS_NINDIRECT]);
    index[(n-OSPFS_NDIRECT-OSPFS_NINDIRECT)%OSPFS_NINDIRECT] = blocknum;
	}
	else
    	return -ENOSPC;
	oi->oi_size = (n+1)*OSPFS_BLKSIZE;
	return 0;

}