Пример #1
0
/*
byte_to_sector(inode, pos)
inode에 해당하는 파일에서 pos번째 값을 가지고 있는 정보가 실제 disk에 어느 sector에 들어있는지 확인한다
이미 pos번째에 해당하는 섹터가 할당되어있다면 테이블에서 그 섹터를 찾아서 return해주면 되고,
그렇지 않다면 allocate_sector을 호출해서 섹터를 할당해주고 다시 byte_to_sector를 실행해준다.
*/
static int
byte_to_sector(const struct inode *inode, off_t pos) 
{
  //printf("@@@@@@@@@@@@@@ byte_to_sector start pos : %d  @@@@@@@@@@@@@@@\n",pos);
  ASSERT (inode != NULL);
  struct inode_disk *inode_d = malloc(sizeof(struct inode_disk));
  int sector;
  //printf("aaaaaaaaaa\n");
  cache_read(inode->sector, inode_d, 512, 0);
  if(bytes_to_sectors(pos) > bytes_to_sectors(inode_d->length))
    sector = -1;
  else
  {
  struct sector_table *dit = malloc(sizeof(struct sector_table));
  cache_read(inode_d->doubly_indirect, dit, 512, 0);
  //printf("cccccccccccc\n");
  struct sector_table *it = malloc(sizeof(struct sector_table));
  int index = (pos / (128 * 512));
  cache_read(dit->table[index], it, 512, 0);
  //printf("dddddddddddd\n");
  sector = it->table[(pos - index * (128 * 512)) / 512];
  free(it);
  free(dit);
  }
  free(inode_d);
  return sector;
}
Пример #2
0
/* Initializes an inode with LENGTH bytes of data and
   wirtes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memeory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length){
    struct inode_disk *disk_inode = NULL;
    bool success = false;
    ASSERT (length >= 0);

    /* If this assertion fails, the inode structure is not exactly
       one sector in size, and you should fix that */
    ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);
    
    disk_inode = calloc(1, sizeof *disk_inode);
    if (disk_inode != NULL){
        size_t sectors = bytes_to_sectors (length);
        disk_inode->length = length;
        disk_inode->magic = INODE_MAGIC;

        if (free_map_allocate (sectors, &disk_inode->start))
        {
            block_write(fs_device, sector, disk_inode);
            success = file_growth(disk_inode, sectors);
            free(disk_inode);
        }
    }
    return success;
}
Пример #3
0
/* Extends the INODE with LENGTH bytes. */
static bool
inode_extend (struct inode *inode, off_t length)
{
  struct inode_disk *disk;
  off_t free_length;
  size_t sectors;
  disk_sector_t sector;
  size_t i;

  lock_acquire (&inode->lock);
  disk = (struct inode_disk *) malloc (sizeof *disk);

  ASSERT (disk != NULL);

  cache_read (inode->sector, disk, 0, DISK_SECTOR_SIZE);

  free_length = disk->sector_count * DISK_SECTOR_SIZE - disk->length;
  sectors = bytes_to_sectors (length - free_length);

  for (i = 0; i < sectors; i++)
    {
      if (!free_map_allocate (1, &sector)
          || !inode_append (inode, sector))
        {
          lock_release (&inode->lock);
          return false;
        }
    }
  disk->length += length;
  cache_write (inode->sector, &disk->length, INODE_OFFSET_LENGTH, 4);
  lock_release (&inode->lock);

  free (disk);
  return true;
}
Пример #4
0
/* Closes INODE and writes it to disk.
   If this was the last reference to INODE, frees its memory.
   If INODE was also a removed inode, frees its blocks. */
void
inode_close (struct inode *inode) 
{
  /* Ignore null pointer. */
  if (inode == NULL)
    return;

  /* Release resources if this was the last opener. */
  if (--inode->open_cnt == 0)
    {
      /* Remove from inode list and release lock. */
      list_remove (&inode->elem);
 
      /* Deallocate blocks if removed. */
      if (inode->removed) 
        {
          int num_sectors = bytes_to_sectors (inode->length);
          inode_release_allocated_sectors (inode, num_sectors); 
          uint8_t buf[BLOCK_SECTOR_SIZE];
          memset (buf, 0, BLOCK_SECTOR_SIZE);
          block_write (fs_device, inode->sector, buf);
          free_map_release (inode->sector, 1);
        }

      free (inode); 
    }
}
Пример #5
0
/* Closes INODE and writes it to disk.
   If this was the last reference to INODE, frees its memory.
   If INODE was also a removed inode, frees its blocks. */
void
inode_close (struct inode *inode) 
{
  /* Ignore null pointer. */
  if (inode == NULL)
    return;

  lock_acquire(&inode_list_lock); 
  lock_acquire(&inode->inode_lock); 

  /* Release resources if this was the last opener. */
  if (--inode->open_cnt == 0)
    {
      /* Remove from inode list. */
      list_remove (&inode->elem);
      
 
      /* Deallocate blocks if the file is marked as removed. */
      if (inode->removed) 
        {
          free_map_release (inode->sector, 1);
          free_map_release (inode->data.start,
                            bytes_to_sectors (inode->data.length)); 
        }
      lock_release(&inode->inode_lock);
      free (inode);
      lock_release(&inode_list_lock);
      return;
    }
  lock_release(&inode->inode_lock);
  lock_release(&inode_list_lock);
}
Пример #6
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length)
{
  struct inode_disk *disk_inode = NULL;
  bool success = false;

  ASSERT (length >= 0);

  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      size_t sectors = bytes_to_sectors (length);
      disk_inode->length = length;
      disk_inode->magic = INODE_MAGIC;
      if (free_map_allocate (sectors, &disk_inode->start))
        {
          block_write (fs_device, sector, disk_inode);
          if (sectors > 0)
            {
              static char zeros[BLOCK_SECTOR_SIZE];
              size_t i;

              for (i = 0; i < sectors; i++)
                block_write (fs_device, disk_inode->start + i, zeros);
            }
          success = true;
        }
      free (disk_inode);
    }
  return success;
}
Пример #7
0
/* Closes INODE and writes it to disk.
   If this was the last reference to INODE, frees its memory.
   If INODE was also a removed inode, frees its blocks. */
void
inode_close (struct inode *inode) 
{
  /* Ignore null pointer. */
  if (inode == NULL)
    return;

  //Acquire both the internal and global inode locks. Internal is required so nobody can change the
  //open_cnt variable while the external lock is required so nobody can get a new pointer to the node
  //while it's being deleted and later freed which would result in a dangling pointer.
  lock_acquire(&inode_list_lock);
  lock_acquire(&inode->internal_lock);
  /* Release resources if this was the last opener. */
  if (--inode->open_cnt == 0)
    {
      /* Remove from inode list and release lock. */
      list_remove (&inode->elem);
 
      /* Deallocate blocks if removed. */
      if (inode->removed) 
        {
          free_map_release (inode->sector, 1);
          free_map_release (inode->data.start,
                            bytes_to_sectors (inode->data.length)); 
        }

      free (inode); 
    }
  else
    {
      lock_release(&inode->internal_lock);
    }
  lock_release(&inode_list_lock);
}
Пример #8
0
static void
deallocate_sectors(struct inode_disk *data)
{
  size_t i, j;
  size_t sectors = bytes_to_sectors(data->length);

  struct sector_table *doubly_indirect_table = calloc(1, sizeof(struct sector_table));
  cache_read(data->doubly_indirect, doubly_indirect_table, 512, 0);
  
  for(i = 0; i < 128; i++)
  {
    if(sectors == 0)
      break;
    struct sector_table *indirect_table = calloc(1, sizeof(struct sector_table));
    cache_read(data->indirect, indirect_table, 512, 0);
    
    for(j = 0; j < 128; j++)
    {
      if(sectors == 0)
        break;
      free_map_release(indirect_table->table[j], 1);
      sectors--;
    }
    free_map_release(data->indirect, 1);
    free(indirect_table);

  }
  //free_map_release(data->doubly_indirect, 1);
  free(doubly_indirect_table);
}
Пример #9
0
/* padding zeros from start_pos (inclusive) to end_pos (exclusive) */
bool zero_padding(struct inode *inode, struct inode_disk *id,
		off_t start_pos, off_t end_pos) {
	ASSERT(lock_held_by_current_thread (&inode->inode_lock));
	static char zeros[BLOCK_SECTOR_SIZE];
	/* padding the first partial sector */
	if (start_pos % BLOCK_SECTOR_SIZE != 0) {
		block_sector_t eof_sector = byte_to_sector(inode, start_pos-1);
		off_t sector_ofs = start_pos % BLOCK_SECTOR_SIZE;
		size_t zero_bytes = BLOCK_SECTOR_SIZE - sector_ofs;
		cache_write(eof_sector, zeros, sector_ofs, zero_bytes);
	}

	/* padding full sectors until end_pos-1 */
	int extra_sectors = (int)bytes_to_sectors(end_pos)-
			(int)bytes_to_sectors(start_pos);
	off_t* record_sectors=malloc(sizeof(off_t) * extra_sectors);
	off_t i,j;
	block_sector_t new_sector=-1;
	for(i=0;i<extra_sectors;i++){
		if (!free_map_allocate (1, &new_sector)) {
			for(j=0;j<i;j++){
				free_map_release(record_sectors[i],1);
			}
			free(record_sectors);
			return false;
		}
		if(!append_sector_to_inode(id,new_sector)){
			for(j=0;j<i;j++){
				free_map_release(record_sectors[i],1);
			}
			free(record_sectors);
			return false;
		}
		cache_write(new_sector, zeros, 0, BLOCK_SECTOR_SIZE);
		record_sectors[i]=new_sector;
		id->length += BLOCK_SECTOR_SIZE;
	}
	/*update the physical length info*/
	id->length=end_pos;
	cache_write(inode->sector, id, 0, BLOCK_SECTOR_SIZE);
	free(record_sectors);
	return true;

}
Пример #10
0
static bool exit_now(struct inode_disk *disk_inode, off_t length){
    size_t cur = bytes_to_sectors(length);
    size_t i,loop;

    // Direct
    loop = cur > 124 ? 0 : cur;
    for (i = loop; i < 124; i++){
        free_map_release(disk_inode->start + i, 1);
    }
    disk_inode->length = length;
    return false;
}
Пример #11
0
/* Closes INODE and writes it to disk.
   If this was the last reference to INODE, frees its memory.
   If INODE was also a removed inode, frees its blocks. */
void
inode_close (struct inode *inode)
{
    /* Ignore null pointer. */
    if (inode == NULL)
        return;
    /* Release resources if this was the last opener. */
    if (--inode->open_cnt == 0)
    {
        /* Remove from inode list and release lock. */
        list_remove (&inode->elem);

        /* Deallocate blocks if removed. */
        if (inode->removed)
        {

            int sectors = bytes_to_sectors(inode->data.length);
            block_sector_t bounce[128];
            block_sector_t inbounce[128];
            int i,j;
            int doublesec = DIV_ROUND_UP(sectors,128);

            free_map_release (inode->sector, 1);

            lock_acquire(&device_lock);
            block_read(fs_device,inode->data.start,bounce);
            lock_release(&device_lock);
            for(i=0; i<doublesec; i++)
            {
                int loop = sectors < 128 ? sectors : 128;
                lock_acquire(&device_lock);
                block_read(fs_device,bounce[i],inbounce);
                lock_release(&device_lock);
                for(j=0; j<loop; j++)
                {
                    free_map_release(inbounce[j],1);
                }
                sectors -=loop;
                free_map_release(bounce[i],1);
            }
            free_map_release(inode->data.start,1);

            //free_map_release (inode->data.start,
            //										bytes_to_sectors (inode->data.length));

        }

        free (inode);
    }
}
Пример #12
0
/* extend inode at sector sector with length bytes */
static bool
inode_extend (struct inode* inode, off_t ext_length)
{
	if(INODE_DEBUG || FILE_DEBUG) printf("INODE: extending inode %u by %i bytes\n", inode->sector, ext_length);

	lock_acquire(&inode->lock);

	bool success = true;

	/* local copy of disk inode */
	struct inode_disk* id = malloc(sizeof(struct inode_disk));
	cache_read(inode->sector, id, 0, sizeof(struct inode_disk));

	/* free space left in bytes */
	off_t free_space = id->sector_count * BLOCK_SECTOR_SIZE - id->length;

	/* needed sectors */
	size_t sectors = bytes_to_sectors (ext_length - free_space);

	/* add sector to inode */
	unsigned i;
	block_sector_t block_sector;
	for(i = 0; i < sectors; i++)
	{
		/* allocate one vector at a time */
		if(free_map_allocate (1, &block_sector))
		{
			/* add new block to inode */
			inode_add_block(inode, block_sector);
		}
		/* not enough space on disk - abort */
		else
		{
			printf("INODE: that should not happen.\n");
			success = false;
			break;
		}
	}
	
	/* increment length and write back */
	id->length += ext_length;
	cache_write(inode->sector, (void *) &id->length, INODE_OFFSET_LENGTH, 4);

	lock_release(&inode->lock);
	
	if(INODE_DEBUG || FILE_DEBUG) printf("INODE: completetd extending inode %u by %i bytes : %u\n", inode->sector, ext_length, (unsigned)success);

	return success;
}
Пример #13
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   disk.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (disk_sector_t sector, off_t length, bool isdir)
{
  //printf("@@@@@@@@@@@@@@@@@@ inode_create start sector : %d length : %d @@@@@@@@@@@@\n",sector,length);
  struct inode_disk *disk_inode = NULL;
  bool success = false;

  ASSERT (length >= 0);

  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      size_t sectors = bytes_to_sectors (length);
      disk_inode->length = length;
      disk_inode->isdir = isdir;
      disk_inode->magic = INODE_MAGIC;
      /*
      if (free_map_allocate (sectors, &disk_inode->start))
        {
          disk_write (filesys_disk, sector, disk_inode);
          if (sectors > 0) 
            {
              static char zeros[DISK_SECTOR_SIZE];
              size_t i;
              
              for (i = 0; i < sectors; i++) 
                disk_write (filesys_disk, disk_inode->start + i, zeros); 
            }
          success = true; 
        }*/
      if(allocate_sectors(disk_inode, sectors, 0))
      {
        //disk_write(filesys_disk, sector, disk_inode);
        cache_write(sector, disk_inode, 512, 0);
        //printf("@@@@@@@@ disk_inode -> disk @@@@@@@\n");
        success = true;
      }
      free (disk_inode);
    }
  //printf("@@@@@@@@@@ inode_create finish @@@@@@@@@\n");
  return success;
}
Пример #14
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length, bool isdir)
{
  struct inode_disk *disk_inode = NULL;
  bool success = false;

  ASSERT (length >= 0);

  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      disk_inode->length = length;
      disk_inode->magic = INODE_MAGIC;
      disk_inode->isdir = isdir ? 1 : 0;

      // Initialize all block entries to -1 (NO_BLOCK).
      int i = 0;
      for(; i < TOTAL_BLOCKS; i++) disk_inode->blocks[i] = NO_BLOCK;

      block_write_cache (fs_device, sector, disk_inode, 0,
                         BLOCK_SECTOR_SIZE, true, -1);
      success = true;

      /* Allocate blocks for inode. */
      struct inode inode;
      inode.data = *disk_inode;
      inode.sector = sector;
      int num_sectors = bytes_to_sectors (length);
      for(i = 0; i < num_sectors; i++) { 
        if (allocate_block (&inode, i) == NO_BLOCK) {
          /* Allocation failed.  Free other blocks. */
          close_blocks_for_inode (&inode);
          success = false;
          break;
        }
      }

      free (disk_inode);
    }
  return success;
}
Пример #15
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length)
{
  struct inode_disk *disk_inode = NULL;
  bool success = true;

  ASSERT (length >= 0);

  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      size_t sectors = bytes_to_sectors (length);
      disk_inode->block_count = 0;
      disk_inode->length = length;
      disk_inode->magic = INODE_MAGIC;
      for (; disk_inode->block_count < sectors; disk_inode->block_count++)
      {
        if (!allocate_block (disk_inode, disk_inode->block_count))
        {
          success = false;
          break;
        }
      }
      if (!success)
      {
        free_inode_blocks (disk_inode);
      }
      else
      {
        cache_write (fs_cache, sector, disk_inode, 0, BLOCK_SECTOR_SIZE);
      }
      free (disk_inode);
    }
  return success;
}
Пример #16
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector_, off_t length, bool is_dir)
{
  uint8_t buf[BLOCK_SECTOR_SIZE];
  bool success = false;

  ASSERT (length >= 0);
  struct inode *inode = malloc (sizeof (struct inode));
  if (inode != NULL)
  {
    inode->sector = sector_;
    inode->length = 0;
    inode->magic = INODE_MAGIC;
    inode->open_cnt = 0;
    inode->removed = 0;
    inode->deny_write_cnt = 0;
    inode->indirect_block = 0;
    inode->doubly_indirect_block = 0;
    inode->is_dir = is_dir;
    memset (inode->direct_blocks, 0, sizeof inode->direct_blocks);

    success = inode_extend (inode, bytes_to_sectors(length));

    if (success)
    {
      inode->length = length;
      inode->max_read_length = inode->length;
      memset (buf, 0, BLOCK_SECTOR_SIZE);
      memcpy (buf, inode, sizeof (*inode));
      block_write (fs_device, inode->sector, buf);
    }

    free (inode);
  }
  return success;
}
Пример #17
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length)
{
  struct inode_disk *disk_inode = NULL;
  bool success = false;

  ASSERT (length >= 0 && length<MAX_SIZE_INODE_DATA);

  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      size_t allocated_sectors = sectors_to_allocate (length);
      size_t data_sectors = bytes_to_sectors(length);
      ASSERT(allocated_sectors >= data_sectors);
      disk_inode->length = length;
      disk_inode->magic = INODE_MAGIC;
      block_sector_t start_sector=0;
      //~ printf("HERERERERERERERERERERERERERERERER1\n");
      if (free_map_allocate (allocated_sectors, &start_sector)) 
        {
		  
          if (data_sectors > 0) 
            {
			  ASSERT(start_sector>0);
              static char zeros[BLOCK_SECTOR_SIZE];
              size_t i;
              uint32_t* buff = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
              int current_sector = start_sector;
              for (i = 0; i < N_DIRECT_BLOCKS && data_sectors>0; i++, data_sectors--){
				//~ printf("HERERERERERERERERERERERERERERERER2 current_sector %d\n", current_sector);
                disk_inode->direct[i]=current_sector;
                //~ cached_write (NULL, current_sector, zeros);
                //~ cache_flush(NULL, current_sector);
                block_write (fs_device, current_sector, zeros);
                
                current_sector++;
              }
              if(data_sectors>0){
				  disk_inode->indirect=current_sector;
				  memset(buff, 0, BLOCK_SECTOR_SIZE);
				  int indir=0;
				  for(i=0; i<N_INDIRECT_POINTERS && data_sectors>0; i++, data_sectors--){
					  //~ printf("HERERERERERERERERERERERERERERERER3\n");
					  buff[i]= current_sector+i+1;
					  indir++;
				  }
				  //~ cached_write(NULL, current_sector, buff);//writing the block containing indirect pointers
				  //~ cache_flush(NULL, current_sector);
				  block_write(fs_device, current_sector, buff);
				  current_sector++;
				  for(i=0; i<indir; i++){
					  //~ printf("HERERERERERERERERERERERERERERERER4\n");
					  block_write(fs_device, current_sector, zeros);
					  //block_flush(NULL, current_sector);
					  current_sector++;
				  }
			  }
			  if(data_sectors>0){
				  disk_inode->double_indirect = current_sector;
				  memset(buff, 0, BLOCK_SECTOR_SIZE);
				  for(i=0; i<DIV_ROUND_UP(data_sectors, N_INDIRECT_POINTERS); i++){
					  //~ printf("HERERERERERERERERERERERERERERERER5\n");
					  buff[i] = current_sector+1+i*(N_INDIRECT_POINTERS+1);
				  }
				  //~ cached_write(NULL, current_sector, buff);
				  //~ cache_flush(NULL, current_sector);
				  block_write(fs_device, current_sector, buff);
				  current_sector++;
				  for(i=0; i<DIV_ROUND_UP(data_sectors, N_INDIRECT_POINTERS); i++){
					  //~ printf("HERERERERERERERERERERERERERERERER6\n");
					  memset(buff, 0, BLOCK_SECTOR_SIZE);
					  int j, indir=0;
					  for(j=0; j<N_INDIRECT_POINTERS, data_sectors>0; j++, data_sectors--){
						  //~ printf("HERERERERERERERERERERERERERERERER7\n");
						buff[j] = current_sector+j+1;
						indir++;
					  }  
					  //~ cached_write(NULL, current_sector, buff);
					  //~ cache_flush(NULL, current_sector);
					  block_write(fs_device, current_sector, buff);
					  current_sector++;
					  for(j=0; j<indir; j++){
						  //~ cached_write(NULL, current_sector, zeros);
						  //~ cache_flush(NULL, current_sector);
						  block_write(fs_device, current_sector, zeros);
						  current_sector++;
					  }
				  }
				  ASSERT(current_sector-start_sector== allocated_sectors);
			  } 
            }
          //~ printf("inode_create: disk_inode->direct[0]=%d\n", disk_inode->direct[0]);
          if(sector!=0){
			//~ cached_write (fs_device, sector, disk_inode);
			//~ cache_flush(NULL, sector);
			block_write (fs_device, sector, disk_inode);
		  }else{
			block_write(fs_device, sector, disk_inode);
		  }
          //~ block_read(fs_device, sector, disk_inode);
          //~ ASSERT(disk_inode->direct[0]!=0);
          success = true; 
        } 
      free (disk_inode);
    }
  return success;
}
Пример #18
0
// Removes and deallocs any blocks within the inode.
void shrink(struct inode_disk *disk_inode, off_t length) {
  size_t sectors = bytes_to_sectors(length);
  struct i_inode_disk *dbl_indirect = NULL;
  struct i_inode_disk *indirect = NULL;
  int i;
  int j;
  int count;
  
  // doubly indirect blocks
  if (sectors < 16636 && disk_inode->block_list[125] != -1) {
    dbl_indirect = disk_inode->block_list[125];
    for (i = 127; i >= 0; i--) {
      if (sectors < 16636 - 128 * (127 - i) && dbl_indirect->block_list[i] != -1) {
        indirect = dbl_indirect->block_list[i];
        for (j = 127; j >= 0; j--) {
          if (sectors < 16636 - 128 * (127 - i) - (127 - j) && indirect->block_list[j] != -1) {
            free_map_release(indirect->block_list[j], 1);
            indirect->block_list[j] = -1;
          }
        }
        if (sectors < 16636 - 128 * (127 - i) - 127) {
          free_map_release(indirect, 1);
          dbl_indirect->block_list[i] = -1;
        }
        else {
          lock_acquire(filesys_lock_list + dbl_indirect->block_list[i]);
          block_write(fs_device, dbl_indirect->block_list[i], indirect);
          lock_release(filesys_lock_list + dbl_indirect->block_list[i]);
        }
      }
    }
    if (sectors < 253) {
      free_map_release(dbl_indirect, 1);
      disk_inode->block_list[125] = -1;
    }
    else {
      lock_acquire(filesys_lock_list + disk_inode->block_list[125]);
      block_write(fs_device, disk_inode->block_list[125], dbl_indirect);
      lock_release(filesys_lock_list + disk_inode->block_list[125]);
    }
  }
  
  // indirect blocks
  if (sectors < 252 && disk_inode->block_list[124] != -1) {
    indirect = disk_inode->block_list[124];
    for (i = 127; i >= 0; i--) {
      if (sectors < 252 - (127 - i)) {
        free_map_release(indirect->block_list[i], 1);
        indirect->block_list[i] = -1;
      }
    }
    if (sectors < 125) {
      free_map_release(indirect, 1);
      disk_inode->block_list[124] = -1;
    }
    else {
      lock_acquire(filesys_lock_list + disk_inode->block_list[124]);
      block_write(fs_device, disk_inode->block_list[124], indirect);
      lock_release(filesys_lock_list + disk_inode->block_list[124]);
    }
  }
  
  // direct blocks
  for (i = 123; i >= 0; i--) {
    if (sectors < 124 - (123 - i) && disk_inode->block_list[i] != -1) {
      free_map_release(disk_inode->block_list[i], 1);
      disk_inode->block_list[i] = -1;
    }
  }
  
  disk_inode->length = length;
}
Пример #19
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
   Returns the number of bytes actually written, which may be
   less than SIZE if end of file is reached or an error occurs.
   (Normally a write at end of file would extend the inode, but
   growth is not yet implemented.) */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset) 
{
  const uint8_t *buffer = buffer_;
  off_t bytes_written = 0;
  //uint8_t *bounce = NULL;
  //struct inode_disk *temp = calloc(1, sizeof(struct inode_disk));

  if (inode->deny_write_cnt)
    return 0;
  struct inode_disk *inode_d;
  inode_d = malloc(sizeof(struct inode_disk));
  cache_read(inode->sector, inode_d, DISK_SECTOR_SIZE, 0);

  if(bytes_to_sectors(offset + size) > bytes_to_sectors(inode_d->length)) // 추가할당이 필요한 경우
  {
    if(!allocate_sectors(inode_d, bytes_to_sectors(offset+size), bytes_to_sectors(inode_d->length)))
      return 0;
    inode_d -> length = offset + size; //할당 완료시 length를 pos로 변경 
    cache_write (inode->sector, inode_d, 512, 0); //변경된 inode_d를 기록
  }
      
 // printf("@@@@@@@@@@@@ file_write start inode length : %d size : %d offset : %d  @@@@@@@@@@@@@@\n",inode_d->length,size,offset);
  while (size > 0) 
    {
      cache_read(inode->sector, inode_d, DISK_SECTOR_SIZE, 0);
      
      /* Sector to write, starting byte offset within sector. */
      int sector_idx = byte_to_sector (inode, offset);
      if(sector_idx == -1)
        break;
    //  printf("@@@@@@@@ find_sector : %d   @@@@@@@@@@@@@\n",sector_idx);
      int sector_ofs = offset % DISK_SECTOR_SIZE;

      /* Bytes left in inode, bytes left in sector, lesser of the two. */
      //off_t inode_left = inode_length (inode) - offset;
      int sector_left = DISK_SECTOR_SIZE - sector_ofs;
      //int min_left = inode_left < sector_left ? inode_left : sector_left;

      /* Number of bytes to actually write into this sector. */
      int chunk_size = size < sector_left ? size : sector_left;
      //printf("chunk_Size??????????????????:%d\n",chunk_size);
      if (chunk_size <= 0)
        break;
      //printf("@@@@@@@@@@@@@ write at : %d location : %x size :%d, offset : %d@@@@@@@@@@@@\n",sector_idx, buffer + bytes_written, chunk_size, sector_ofs);
      cache_write(sector_idx, buffer + bytes_written, chunk_size, sector_ofs);
      /*
      cache_read(inode->sector, temp, 512, 0);

      if(offset > temp->length)
      {
        temp->length = offset;
        cache_write(inode->sector, temp, 512, 0);
      }
      */
      /*
      if (sector_ofs == 0 && chunk_size == DISK_SECTOR_SIZE) 
        {
          //Write full sector directly to disk. 
          //disk_write (filesys_disk, sector_idx, buffer + bytes_written); 
          cache_write(sector_idx, buffer + bytes_written, 512, 0);
        }
      else 
        {
          
           //We need a bounce buffer. 
          if (bounce == NULL) 
            {
              bounce = malloc (DISK_SECTOR_SIZE);
              if (bounce == NULL)
                break;
            }
           If the sector contains data before or after the chunk
             we're writing, then we need to read in the sector
             first.  Otherwise we start with a sector of all zeros. 
          
          if (sector_ofs > 0 || chunk_size < sector_left) 
            disk_read (filesys_disk, sector_idx, bounce);
          else
            memset (bounce, 0, DISK_SECTOR_SIZE);
          memcpy (bounce + sector_ofs, buffer + bytes_written, chunk_size);
          disk_write (filesys_disk, sector_idx, bounce); 
          
          if(!(sector_ofs > 0 || chunk_size < sector_left))
            cache_write(sector_idx, 0, 512, 0);
          cache_write(sector_idx, buffer + bytes_written, chunk_size, sector_ofs);
        }*/
        
      /* Advance. */
      size -= chunk_size;
      offset += chunk_size;
      bytes_written += chunk_size;
      //printf("%d %d\n",inode->sector,offset);
      if(offset > inode_d->length){
        inode_d->length = offset;
        //printf("update!!!!!");
        cache_write(inode->sector, inode_d, DISK_SECTOR_SIZE, 0);
      }
    }
  //free (bounce);
  free(inode_d);   
  //printf("@@@@@@@@@@@@ file_write finish @@@@@@@@@@@\n");
  //printf("%d\n",bytes_written);
  return bytes_written;
}
Пример #20
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length, bool is_dir)
{
  struct inode_disk *disk_inode = NULL;

  ASSERT (length >= 0);
  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      int sectors = (int)bytes_to_sectors (length);
      disk_inode->length = length;
      disk_inode->magic = INODE_MAGIC;
      disk_inode->is_dir = is_dir;

      int i;
      block_sector_t sector_idx = 0;
      static char zeros[BLOCK_SECTOR_SIZE];
      bool allocate_failed = false;

      /* allocate sectors for data and write all zeros to sectors*/
      int direct_sector_num = sectors < DIRECT_INDEX_NUM ?
    		  sectors : DIRECT_INDEX_NUM;
      int indirect_sector_num = (sectors-DIRECT_INDEX_NUM) <
    		  INDEX_PER_SECTOR ? (sectors - DIRECT_INDEX_NUM) :
    				  INDEX_PER_SECTOR;
      int double_indirect_sector_num = sectors - DIRECT_INDEX_NUM
    		  - INDEX_PER_SECTOR;

      /* allocate direct sectors */
      for (i = 0; i < direct_sector_num; i++) {
    	  	  if (free_map_allocate (1, &sector_idx)) {
    	  		  disk_inode->direct_idx[i] = sector_idx;
    	  		  cache_write(sector_idx, zeros, 0, BLOCK_SECTOR_SIZE);
    	  	  } else {
    	  		  allocate_failed = true;
    	  		  break;
    	  	  }
      }
      /* release allocated direct sectors when failed to allocate */
      if (allocate_failed) {
    	  	  free_map_release_direct(disk_inode, i);
    	  	  free (disk_inode);
    	  	  return false;
      }

      static struct indirect_block ib;
      /* allocate single indirect sectors */
      if(indirect_sector_num > 0){
			if (!free_map_allocate (1, &disk_inode->single_idx)) {
				free_map_release_all_direct(disk_inode);
				free (disk_inode);
				return false;
			}

			for (i = 0; i < indirect_sector_num; i++) {
			  if (free_map_allocate (1, &sector_idx)) {
				  ib.sectors[i] = sector_idx;
				  cache_write(sector_idx, zeros, 0, BLOCK_SECTOR_SIZE);
			  } else {
				  allocate_failed = true;
				  break;
			  }
			}

			/* release all direct sectors and allocated single indirect
			 * sectors when failed to allocate */
			if (allocate_failed) {
				free_map_release_all_direct(disk_inode);
				free_map_release_single_indirect(&ib, i);
				free_map_release(disk_inode->single_idx, 1);
				free (disk_inode);
				return false;
			}

			cache_write(disk_inode->single_idx, &ib, 0, BLOCK_SECTOR_SIZE);
      }



      /* allocate double indirect sectors */
      if(double_indirect_sector_num > 0){
    	  	  if (!free_map_allocate (1, &disk_inode->double_idx)) {
    	  		  free_map_release_all_direct(disk_inode);
    	  		  free_map_release_all_single_indirect(&ib);
    	  		  free_map_release (disk_inode->single_idx, 1);
    	  		  free (disk_inode);
    	  		  return false;
		  }

    	  	  off_t double_level_end_idx =
    	  			  (double_indirect_sector_num-1) / INDEX_PER_SECTOR;
    	      off_t single_level_end_idx =
    	    		  (double_indirect_sector_num-1) % INDEX_PER_SECTOR;
    	      int i, j;
    	      /*double indirect index block*/
    	      static struct indirect_block db;
    	      /*buffer the single indirect index block in double
    	       * indirect index block*/
    	      static struct indirect_block single_ib;
    	      /* allocate all full single indirect block */
    	      for (i = 0; i < double_level_end_idx; i++) {
			  if (!free_map_allocate (1, &db.sectors[i])){
				  free_map_release_all_direct(disk_inode);
				  free_map_release_all_single_indirect(&ib);
				  free_map_release (disk_inode->single_idx, 1);
				  free_map_release_double_indirect (&db, i, 0);
				  free_map_release (disk_inode->double_idx, 1);
				  free (disk_inode);
				  return false;
			  }

			  /* fully allocate the whole single indirect block */
    	    	  	  for (j = 0; j < INDEX_PER_SECTOR; j++) {
    	    	  		  if (free_map_allocate (1, &sector_idx)) {
    	    	  			  single_ib.sectors[j] = sector_idx;
    	    	  			  cache_write(sector_idx, zeros, 0, BLOCK_SECTOR_SIZE);
    	    	  		  } else {
    	    	  			  allocate_failed = true;
    	    	  			  break;
    	    	  		  }
    	    	  	  }


    	    	  	  if (allocate_failed) {
    	    	  		  free_map_release_all_direct(disk_inode);
    	    	  		  free_map_release_all_single_indirect(&ib);
				  free_map_release (disk_inode->single_idx, 1);
				  free_map_release_double_indirect (&db, i, j);
				  free_map_release (disk_inode->double_idx, 1);
				  free (disk_inode);
				  return false;
    	    	  	  }

    	    	  	  cache_write(db.sectors[i], &single_ib, 0, BLOCK_SECTOR_SIZE);
    	      }

    	      /* allocate the last partial/full single indirect block */
    	      if (!free_map_allocate (1, &db.sectors[double_level_end_idx])){
			  free_map_release_all_direct(disk_inode);
			  free_map_release_all_single_indirect(&ib);
			  free_map_release (disk_inode->single_idx, 1);
			  free_map_release_double_indirect (&db,
					  double_level_end_idx, 0);
			  free_map_release (disk_inode->double_idx, 1);
			  free (disk_inode);
			  return false;
    	      }
    	      /* partially or fully (depend on single_level_end_idx)
    	       * allocate the last single indirect block */
		  for (j = 0; j <= single_level_end_idx; j++) {
			  if (free_map_allocate (1, &sector_idx)) {
				  single_ib.sectors[j] = sector_idx;
				  cache_write(sector_idx, zeros, 0, BLOCK_SECTOR_SIZE);
			  } else {
				  allocate_failed = true;
				  break;
			  }
		  }


		  if (allocate_failed) {
			  free_map_release_all_direct(disk_inode);
			  free_map_release_all_single_indirect(&ib);
			  free_map_release (disk_inode->single_idx, 1);
			  free_map_release_double_indirect (&db,
					  double_level_end_idx, j);
			  free_map_release (disk_inode->double_idx, 1);
			  free (disk_inode);
			  return false;
		  }

		  cache_write(db.sectors[double_level_end_idx],
				  &single_ib, 0, BLOCK_SECTOR_SIZE);
		  /* update inode_disk(metadata) after successfully
		   * allocate all necessary sectors */
		  cache_write(disk_inode->double_idx, &db, 0, BLOCK_SECTOR_SIZE);
      }


      /* write inode_disk(metadata) to sector */
      cache_write(sector, disk_inode, 0, BLOCK_SECTOR_SIZE);
      free (disk_inode);
      return true;
    }
  return false;
}
Пример #21
0
/* Closes INODE and writes it to disk. return if the inode is freed
   If this was the last reference to INODE, frees its memory.
   If INODE was also a removed inode, frees its blocks. */
bool
inode_close (struct inode *inode) 
{
	bool inode_freed = false;
  /* Ignore null pointer. */
  if (inode == NULL)
    return inode_freed;

  bool holding_open_inodes_lock = lock_held_by_current_thread
		  (&open_inodes_lock);
  if (!holding_open_inodes_lock) {
	  lock_acquire(&open_inodes_lock);
  }

  bool holding_inode_lock = lock_held_by_current_thread
		  (&inode->inode_lock);
  if (!holding_inode_lock) {
	  lock_acquire(&inode->inode_lock);
  }
  /* Release resources if this was the last opener. */
  if (--inode->open_cnt == 0)
  {
      /* Remove from inode list and release lock. */
      list_remove (&inode->elem);
      if (!holding_open_inodes_lock && lock_held_by_current_thread
    		  (&open_inodes_lock)) {
    	  	  lock_release(&open_inodes_lock);
      }
      /* Deallocate blocks if removed. */
      if (inode->removed) 
      {
    	  	  /* retrieve inode_disk(metadata) from sector */
          struct inode_disk id;
          cache_read(inode->sector, INVALID_SECTOR_ID, &id, 0,
        		  BLOCK_SECTOR_SIZE);

          int sectors = (int)bytes_to_sectors (id.length);

          int direct_sector_num = sectors < DIRECT_INDEX_NUM ?
        		  sectors : DIRECT_INDEX_NUM;
          int indirect_sector_num = (sectors -
        		  DIRECT_INDEX_NUM) < INDEX_PER_SECTOR ?
        				  (sectors - DIRECT_INDEX_NUM) : INDEX_PER_SECTOR;
          int double_indirect_sector_num = sectors -
        		  DIRECT_INDEX_NUM - INDEX_PER_SECTOR;

          /* release data sectors */
          free_map_release_direct(&id, direct_sector_num);

          if (indirect_sector_num > 0){
        	  	  static struct indirect_block ib;
        	  	  if (double_indirect_sector_num > 0) {
        	  		  cache_read(id.single_idx, id.double_idx, &ib,
        	  				  0, BLOCK_SECTOR_SIZE);
        	  	  } else {
        	  		  cache_read(id.single_idx, INVALID_SECTOR_ID,
        	  				  &ib, 0, BLOCK_SECTOR_SIZE);
        	  	  }
        	  	  free_map_release_single_indirect(&ib, indirect_sector_num);
        	  	  free_map_release (id.single_idx, 1);
          }

          if (double_indirect_sector_num > 0) {
        	  	  static struct indirect_block db;
        	  	  cache_read(id.double_idx, INVALID_SECTOR_ID,
        	  			  &db, 0, BLOCK_SECTOR_SIZE);
        	  	  off_t double_level_end_idx =
        	  			  (double_indirect_sector_num-1) / INDEX_PER_SECTOR;
        	  	  off_t single_level_end_idx =
        	  			  (double_indirect_sector_num-1) % INDEX_PER_SECTOR;
        	  	  free_map_release_double_indirect(&db,
        	  			  double_level_end_idx, single_level_end_idx+1);
        	  	  free_map_release (id.double_idx, 1);
          }


          /* release inode_disk(metadata) sector */
          free_map_release (inode->sector, 1);
      }

      if (lock_held_by_current_thread (&inode->inode_lock)) {
    	  	  lock_release(&inode->inode_lock);
      }
      free (inode);
      inode_freed = true;
  }

  if (!holding_open_inodes_lock && lock_held_by_current_thread (
		  &open_inodes_lock)) {
	  lock_release(&open_inodes_lock);
  }

  if (inode != NULL) {
	  if (!holding_inode_lock && lock_held_by_current_thread (
			  &inode->inode_lock)) {
		  lock_release(&inode->inode_lock);
	  }
  }

  return inode_freed;
}
Пример #22
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
   Returns the number of bytes actually written, which may be
   less than SIZE if end of file is reached or an error occurs. */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset) 
{
  const uint8_t *buffer = buffer_;
  off_t bytes_written = 0;
  struct cached_block *cached_block;
  block_sector_t sector_idx = -1;
  bool extending = false;

  if (inode->deny_write_cnt)
    return 0;

  //grow inode if necessary
  
  if (offset + size > inode->max_read_length)
  {

    extending = true;
    lock_acquire (&inode->extend_lock);
    if (offset + size > inode->max_read_length)
    {
      int num_blocks_to_add = bytes_to_sectors (offset + size ) - bytes_to_sectors (inode_length (inode));
      if (num_blocks_to_add > 0)
      {
        if (!inode_extend(inode, num_blocks_to_add))
        {
          lock_release (&inode->extend_lock);
          return 0;
        }
      }
      inode->length = offset + size ;
    }
    else
    {
      extending = false;
      lock_release (&inode->extend_lock);
    }
  }

  while (size > 0) 
  {
    /* Sector to write, starting byte offset within sector. */
    sector_idx = byte_to_sector (inode, offset);
    int sector_ofs = offset % BLOCK_SECTOR_SIZE;

    /* Bytes left in inode, bytes left in sector, lesser of the two. */
    off_t inode_left = inode_length (inode) - offset;
    int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
    int min_left = inode_left < sector_left ? inode_left : sector_left;

    /* Number of bytes to actually write into this sector. */
    int chunk_size = size < min_left ? size : min_left;
    if (chunk_size <= 0)
      break;

    cached_block = cache_insert (sector_idx);

    cached_block->active_r_w ++ ;
    lock_release (&cached_block->lock);


    thread_current ()->cache_block_being_accessed = cached_block;
    memcpy (cached_block->data + sector_ofs, buffer + bytes_written, chunk_size);
    cached_block->dirty = true;

    thread_current ()->cache_block_being_accessed = NULL;

    lock_acquire (&cached_block->lock);
    cached_block->active_r_w --;
    if (cached_block->active_r_w == 0)
      cond_broadcast (&cached_block->r_w_done, &cached_block->lock);
    lock_release (&cached_block->lock);


    /* Advance. */
    size -= chunk_size;
    offset += chunk_size;
    bytes_written += chunk_size;

  }

  if (((int)sector_idx != -1) && (bytes_to_sectors (inode->max_read_length) > sector_idx))
  {
    block_sector_t next_sector = byte_to_sector (inode, offset + BLOCK_SECTOR_SIZE);
    cache_read_ahead (next_sector);
  }

  if (extending)
  {
    inode->max_read_length = inode->length;
    uint8_t buf[BLOCK_SECTOR_SIZE];
    memset (buf, 0, BLOCK_SECTOR_SIZE);
    memcpy (buf, inode, sizeof (*inode));
    block_write (fs_device, inode->sector, buf);
    lock_release (&inode->extend_lock);
  }

  return bytes_written;
}
Пример #23
0
/* set the new_sector to the first non-allocated sector in the inode
 * must acquire inode lock before calling it */
bool append_sector_to_inode(struct inode_disk *id,
		block_sector_t new_sector) {
	int sectors = (int)bytes_to_sectors(id->length);
	static struct indirect_block ib;
	static struct indirect_block db;

	if (sectors <= DIRECT_INDEX_NUM) {
		if (sectors < DIRECT_INDEX_NUM) {
			/*within direct index part*/
			id->direct_idx[sectors] = new_sector;
		} else {
			/*use up direct index part, start using single indirect index*/
			if (!free_map_allocate (1, &id->single_idx)) {
				return false;
			}
			ib.sectors[0] = new_sector;
			cache_write(id->single_idx, &ib, 0, BLOCK_SECTOR_SIZE);
		}
	} else if (sectors <= DIRECT_INDEX_NUM+INDEX_PER_SECTOR) {
		if (sectors < DIRECT_INDEX_NUM+INDEX_PER_SECTOR) {
			/*within single indirect index part*/
			cache_read(id->single_idx, INVALID_SECTOR_ID,
					&ib, 0, BLOCK_SECTOR_SIZE);
			ib.sectors[sectors-DIRECT_INDEX_NUM] = new_sector;
			cache_write(id->single_idx, &ib, 0, BLOCK_SECTOR_SIZE);
		} else {
			/*use up single indirect index part, start using
			 * double indirect index*/
			if (!free_map_allocate (1, &id->double_idx)) {
				return false;
			}
			static struct indirect_block single_ib;
			if (!free_map_allocate (1, &db.sectors[0])) {
				free_map_release (id->double_idx, 1);
				return false;
			}
			single_ib.sectors[0] = new_sector;
			cache_write(db.sectors[0], &single_ib, 0, BLOCK_SECTOR_SIZE);
			cache_write(id->double_idx, &db, 0, BLOCK_SECTOR_SIZE);
		}
	} else {
		size_t sectors_left=sectors - DIRECT_INDEX_NUM - INDEX_PER_SECTOR;
		if(sectors_left%INDEX_PER_SECTOR ==0){
			/*on the edge of one double indirect index, need
			 *  to allocate another single indirect index in
			 *  the double indirect index*/
			cache_read(id->double_idx, INVALID_SECTOR_ID,
					&db, 0, BLOCK_SECTOR_SIZE);
			if (!free_map_allocate (1,
					&db.sectors[sectors_left/INDEX_PER_SECTOR])) {
				return false;
			}
			 ib.sectors[0]=new_sector;
			cache_write(db.sectors[sectors_left/INDEX_PER_SECTOR],
					&ib, 0, BLOCK_SECTOR_SIZE);
			cache_write(id->double_idx, &db, 0, BLOCK_SECTOR_SIZE);
		}else{
			cache_read(id->double_idx, INVALID_SECTOR_ID,
					&db, 0, BLOCK_SECTOR_SIZE);
			cache_read(db.sectors[sectors_left/INDEX_PER_SECTOR],
					INVALID_SECTOR_ID, &ib, 0, BLOCK_SECTOR_SIZE);
			ib.sectors[sectors_left%INDEX_PER_SECTOR]=new_sector;
			cache_write(db.sectors[sectors_left/INDEX_PER_SECTOR],
					&ib, 0, BLOCK_SECTOR_SIZE);
		}

	}
	return true;
}
Пример #24
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
   Returns the number of bytes actually written, which may be
   less than SIZE if end of file is reached or an error occurs.
   (Normally a write at end of file would extend the inode, but
   growth is not yet implemented.) */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset)
{
  const uint8_t *buffer = buffer_;
  off_t bytes_written = 0;

  if (inode->deny_write_cnt)
    return 0;

  if (offset >= MAX_FILE_LENGTH)
    return 0;

  if (size > MAX_FILE_LENGTH - offset)
    size = MAX_FILE_LENGTH - offset;

  if (size + offset <= MAX_FILE_LENGTH &&
      size + offset > inode->data.length)
  {
    /* extend file */
    off_t length = size + offset;
    size_t sectors = bytes_to_sectors (length);
    for (;inode->data.block_count < sectors; inode->data.block_count++)
    {
      if (!allocate_block (&inode->data, inode->data.block_count))
      {
        /* update to the inode sector */
        cache_write (fs_cache, inode->sector, &inode->data, 0, BLOCK_SECTOR_SIZE);
        return 0;
      }
    }
    inode->data.length = length;

    /* update to the inode sector */
    cache_write (fs_cache, inode->sector, &inode->data, 0, BLOCK_SECTOR_SIZE);
  }

  while (size > 0)
    {
      /* Sector to write, starting byte offset within sector. */
      block_sector_t sector_idx = byte_to_sector (inode, offset);
      int sector_ofs = offset % BLOCK_SECTOR_SIZE;

      /* Bytes left in inode, bytes left in sector, lesser of the two. */
      off_t inode_left = inode_length (inode) - offset;
      int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
      int min_left = inode_left < sector_left ? inode_left : sector_left;

      /* Number of bytes to actually write into this sector. */
      int chunk_size = size < min_left ? size : min_left;
      if (chunk_size <= 0)
        break;

      cache_write (fs_cache, sector_idx, buffer + bytes_written,
        sector_ofs, chunk_size);

      /* Advance. */
      size -= chunk_size;
      offset += chunk_size;
      bytes_written += chunk_size;
    }

  return bytes_written;
}
Пример #25
0
// Grows the file to a given length.
bool grow(struct inode_disk *disk_inode, off_t length) {
  size_t sectors = bytes_to_sectors(length);
  size_t cur_sectors = bytes_to_sectors(disk_inode->length);
  struct i_inode_disk *indirect = NULL;
  struct i_inode_disk *dbl_indirect = NULL;
  uint32_t i;
  uint32_t j;
  block_sector_t file_sector = 0;
  block_sector_t indirect_sector = 0;
  block_sector_t dbl_indirect_sector = 0;
  static char zeros[BLOCK_SECTOR_SIZE];
  
  size_t cur = bytes_to_sectors(disk_inode->length);
  int growth = sectors - cur;
  if (growth <= 0) {
    disk_inode->length = length;
    return true;
  }
  
  // direct blocks
  if (cur < 124) {
    for (i = cur; i < sectors && i < 124; i++) {
      if (free_map_allocate(1, &file_sector)) {
        lock_acquire(filesys_lock_list + file_sector);
        block_write(fs_device, file_sector, zeros);
        lock_release(filesys_lock_list + file_sector);
        disk_inode->block_list[i] = file_sector;
        growth--;
      }
      else {
        shrink(disk_inode, cur_sectors);
        return false;
      }
    }
    cur = 124;
  }
  if (growth <= 0) {
    disk_inode->length = length;
    return true;
  }
  
  // indirect blocks
  if (cur < 252) {
    if (disk_inode->block_list[124] == -1) {
      indirect = calloc(1, sizeof *indirect);
      if (indirect == NULL) {
        shrink(disk_inode, cur_sectors);
        return false;
      }
      if (free_map_allocate(1, &indirect_sector)) {
        for (i = 0; i < 128; i++) {
          indirect->block_list[i] = -1;
        }
      }
      else {
        shrink(disk_inode, cur_sectors);
        return false;
      }
    }
    else {
      block_read(fs_device, disk_inode->block_list[124], indirect);
    }
    for (i = cur; i < (sectors - 124) && i < 128; i++) {
      if (free_map_allocate(1, &file_sector)) {
        lock_acquire(filesys_lock_list + file_sector);
        block_write(fs_device, file_sector, zeros);
        lock_release(filesys_lock_list + file_sector);
        indirect->block_list[i] = file_sector;
        growth--;
      }
      else {
        shrink(disk_inode, cur_sectors);
        return false;
      }
    }
    if (disk_inode->block_list[124] == -1) {
      disk_inode->block_list[124] = indirect_sector;
      lock_acquire(filesys_lock_list + disk_inode->block_list[124]);
      block_write(fs_device, disk_inode->block_list[124], indirect);
      lock_release(filesys_lock_list + disk_inode->block_list[124]);
      free(indirect);
    }
    else {
      lock_acquire(filesys_lock_list + disk_inode->block_list[124]);
      block_write(fs_device, disk_inode->block_list[124], indirect);
      lock_release(filesys_lock_list + disk_inode->block_list[124]);
    }
    cur = 252;
  }
  if (growth <= 0) {
    disk_inode->length = length;
    return true;
  }
  
  // doubly indirect blocks
  if (cur < 16636) {
    if (disk_inode->block_list[125] == -1) {
      dbl_indirect = calloc(1, sizeof *dbl_indirect);
      if (dbl_indirect == NULL) {
        shrink(disk_inode, cur);
        return false;
      }
      if (free_map_allocate(1, &dbl_indirect_sector)) {
        for (i = 0; i < 128; i++) {
          dbl_indirect->block_list[i] = -1;
        }
      }
      else {
        shrink(disk_inode, cur);
        return false;
      }
    }
    else {
      block_read(fs_device, disk_inode->block_list[125], dbl_indirect);
    }
    for (i = (cur - 252) / 128; i < (sectors - 252) / 128 + 1 && i < 128; i++) {
      if (dbl_indirect->block_list[i] == -1) {
        indirect = calloc(1, sizeof *indirect);
        if (indirect == NULL) {
          shrink(disk_inode, cur_sectors);
          return false;
        }
        if (free_map_allocate(1, &indirect_sector)) {
          for (i = 0; i < 128; i++) {
            indirect->block_list[i] = -1;
          }
        }
        else {
          shrink(disk_inode, cur_sectors);
          return false;
        }
      }
      else {
        block_read(fs_device, dbl_indirect->block_list[i], indirect);
      }
      for (j = cur - 252 - (i * 128); j < sectors - 252 - (i * 128) + 1 && j < 128; j++) {
        if (free_map_allocate(1, &file_sector)) {
          lock_acquire(filesys_lock_list + file_sector);
          block_write(fs_device, file_sector, zeros);
          lock_release(filesys_lock_list + file_sector);
          indirect->block_list[i] = file_sector;
          growth--;
        }
        else {
          shrink(disk_inode, cur_sectors);
          return false;
        }
      }
      if (dbl_indirect->block_list[i] == -1) {
        dbl_indirect->block_list[i] = indirect_sector;
        lock_acquire(filesys_lock_list + dbl_indirect->block_list[i]);
        block_write(fs_device, dbl_indirect->block_list[i], indirect);
        lock_release(filesys_lock_list + dbl_indirect->block_list[i]);
        free(indirect);
      }
      else {
        lock_acquire(filesys_lock_list + dbl_indirect->block_list[i]);
        block_write(fs_device, dbl_indirect->block_list[i], indirect);
        lock_release(filesys_lock_list + dbl_indirect->block_list[i]);
      }
    }
    if (disk_inode->block_list[125] == -1) {
      disk_inode->block_list[125] = dbl_indirect_sector;
      lock_acquire(filesys_lock_list + disk_inode->block_list[125]);
      block_write(fs_device, disk_inode->block_list[125], dbl_indirect);
      lock_release(filesys_lock_list + disk_inode->block_list[125]);
      free(dbl_indirect);
    }
    else {
      lock_acquire(filesys_lock_list + disk_inode->block_list[125]);
      block_write(fs_device, disk_inode->block_list[125], dbl_indirect);
      lock_release(filesys_lock_list + disk_inode->block_list[125]);
    }
  }
  if (growth <= 0) {
    disk_inode->length = length;
    return true;
  }
  return false; // should never get here
}
Пример #26
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length)
{
    struct inode_disk *disk_inode = NULL;
    bool success = false;
    bool fail = false;
    size_t i,j;

    ASSERT (length >= 0);

    /* If this assertion fails, the inode structure is not exactly
       one sector in size, and you should fix that. */
    ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

    disk_inode = calloc (1, sizeof *disk_inode);
    if (disk_inode != NULL)
    {
        size_t sectors = bytes_to_sectors (length);

        size_t single_sectors = sectors;
        size_t double_sectors = sectors/128 + 1;
        if(length ==0)
        {
            single_sectors = 1;
            single_sectors = 1;
        }

        block_sector_t extern_block[128] = {0};
        block_sector_t inner_block[128] = {0};

        disk_inode->length = length;
        disk_inode->magic = INODE_MAGIC;

        if (free_map_allocate (1, &disk_inode->start))
        {
            block_write (fs_device, sector, disk_inode);
            for(i=0; i<double_sectors; i++)
            {
                if(!free_map_allocate(1, &extern_block[i]))
                    fail = true;
                //if(sector == 1)
                //printf("extern block[%d] = %d\n",i,extern_block[i]);
            }
            if(!fail)
            {
                block_write(fs_device,disk_inode->start,(void *)extern_block);

                static char zeros[BLOCK_SECTOR_SIZE];
                for(i=0; i<double_sectors; i++)
                {
                    int loop = (single_sectors < (BLOCK_SECTOR_SIZE/sizeof(block_sector_t)) ? single_sectors : 128);

                    for(j=0; j<loop; j++)
                    {
                        if(!free_map_allocate(1,&inner_block[j]))
                            fail = true;
                        else
                        {
                            block_write(fs_device,inner_block[j],zeros);
                            //if(sector == 1)
                            //printf("inner block[%d] = %d\n",j,inner_block[i]);
                        }
                    }
                    block_write(fs_device,extern_block[i],(void *)inner_block);
                    single_sectors -= loop;
                }
                if(!fail)
                    success = true;
                else
                {
                    success = false;
                    printf("FAIL!!!!\n");
                }
                /*
                if (sectors > 0)
                	{
                		static char zeros[BLOCK_SECTOR_SIZE];
                		size_t i;

                		for (i = 0; i < sectors; i++)
                			block_write (fs_device, disk_inode->start + i, zeros);
                	}
                */
            }
            else
            {
                success = false;
                printf("Fail to allocate new memory!!!\n");
            }
        }
        free (disk_inode);
    }
    return success;
}
Пример #27
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
	 Returns the number of bytes actually written, which may be
	 less than SIZE if end of file is reached or an error occurs.
	 (Normally a write at end of file would extend the inode, but
	 growth is not yet implemented.) */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset)
{
    const uint8_t *buffer = buffer_;
    off_t bytes_written = 0;
    uint8_t *bounce = NULL;
    /* Debugging */
    bool debug = false;

    if (inode->deny_write_cnt)
        return 0;

    //printf("inode_length : %d\n",inode_length(inode));
    ASSERT(inode->sector <20000);
    //printf("*node[%d]->extension=%d \n", inode->sector, inode->extension);
    while(inode->extension);
    //printf("inode_write_at called size: %d, offset : %d, inode_length : %d\n",size,offset,inode->data.length);
    while (size > 0)
    {
        /* Sector to write, starting byte offset within sector. */
        block_sector_t sector_idx = byte_to_sector (inode, offset);
        int sector_ofs = offset % BLOCK_SECTOR_SIZE;

        /* Bytes left in inode, bytes left in sector, lesser of the two. */
        off_t inode_left = inode_length (inode) - offset;
        int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
        int min_left = inode_left < sector_left ? inode_left : sector_left;

        /* Number of bytes to actually write into this sector. */
        int chunk_size = size < min_left ? size : min_left;

        struct cache * cache = find_cache(sector_idx);

        //if(debug) printf("sector_idx : %d\n",sector_idx);

        if(offset > inode_length(inode))
        {
            //printf("setting node[%d]->extension=true \n", inode->sector);
            inode->extension = true;
            //printf("You made me true\n");
            int left = (offset - inode_length(inode));
            int i;
            int sectors = (left+1)/BLOCK_SECTOR_SIZE;

            //printf("Offset Over\n");
            block_sector_t new_sector;

            int check = inode_length(inode) + BLOCK_SECTOR_SIZE - inode_length(inode)%512+1;
            inode->data.length += left;
            block_write(fs_device,inode->sector,&(inode->data));

            //printf("offset inode length increase from :%d to %d sector num : %d check : %d\n",inode_length(inode),inode_length(inode)-left,sectors,check);

            for(i=0; i<sectors; i++)
            {
                //printf("check is : %d\n",check);
                if(!free_map_allocate(1,&new_sector))
                {
                    printf("Fail to allocate freemap\n");
                    ASSERT(false);
                }
                updateBlock(inode,check,new_sector);
                //printf("Allocate new Sector : %d\n",new_sector);
                check += BLOCK_SECTOR_SIZE;
            }
            //debug = true;
            continue;
        }
        else if((size >= inode_left - offset) && min_left == 0)
        {
            int sector_num;
            int i;

            //printf("Size Over\n");
            if((size-sector_left+1) <=0)
                sector_num = 0;
            else
                sector_num = bytes_to_sectors((size-sector_left)+1);

            //printf("size : %d , offset : %d, sector_left : %d\n",size,offset,sector_left);
            block_sector_t new_sector;
            int check = inode_length(inode) + sector_left ;
            //printf("setting node[%d]->extension=true \n", inode->sector);
            inode->extension = true;
            //printf("You made me true\n");
            //file_extension(inode,buffer+bytes_written,size);
            inode->data.length = inode->data.length + size;
            block_write(fs_device,inode->sector,&(inode->data));
            //printf("Sector_left : %d\n",sector_left);
            //printf("size inode length increase from :%d to %d now sector num : %d sector_num : %d\n",inode_length(inode),inode_length(inode)-size,sector_idx,sector_num);

            for(i=0; i<sector_num; i++)
            {
                if(!free_map_allocate(1,&new_sector))
                {
                    printf("Freemap Fail\n");
                    ASSERT(false);
                }
                updateBlock(inode,check,new_sector);
                //printf("Allocate new Sector : %d\n",new_sector);
                //	print_table_info(inode);
                check +=BLOCK_SECTOR_SIZE;
            }
            debug = true;
            continue;
        }
        else if(sector_idx == -1)
        {
            print_table_info(inode);
            //printf("offset : %d inode : %#x inode_sector : %d length : %d\n",offset,inode,inode->sector,inode_length(inode));
        }

        if(debug)
        {
        }

        //ASSERT(sector_idx < 20000);
        if (chunk_size <= 0)
            break;
        /*
        			if(debug)
        			{
        				print_table_info(inode);
        			}
        	*/
        //printf("inode read at called chunksize : %d , sector_ofs : %d, sector_idx : %d\n",chunk_size,sector_ofs,sector_idx);
        if(cache == NULL)
        {
            cache = add_cache(sector_idx);

            if(cache == NULL)
            {
                print_table_info(inode);
                printf("read Error\n");
                return bytes_written;
            }
        }
        cache->accessed = true;
        cache->pin = true;
        //if(inode_left - sector_ofs > 512)
        //	read_ahead(sector_idx +1);
        write_cache(cache , buffer+bytes_written , sector_ofs ,chunk_size);
        /* Advance. */
        cache->pin = false;
        size -= chunk_size;
        offset += chunk_size;
        bytes_written += chunk_size;
    } // free (bounce);
    if(inode->extension == true)
    {
        //printf("set node[%d]->extension as false\n", inode->sector);
        inode->extension = false;
        ASSERT(inode->extension==false);
    }
    return bytes_written;
}
Пример #28
0
/* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
   Returns the number of bytes actually read, which may be less
   than SIZE if an error occurs or end of file is reached. */
off_t
inode_read_at (struct inode *inode, void *buffer_, off_t size, off_t offset) 
{
  uint8_t *buffer = buffer_;
  off_t bytes_read = 0;
  struct cached_block *cached_block;
  block_sector_t sector_idx = -1;

  while (size > 0) 
    {
      /* Disk sector to read, starting byte offset within sector. */
      sector_idx = byte_to_sector (inode, offset);
      int sector_ofs = offset % BLOCK_SECTOR_SIZE;

      /* Bytes left in inode, bytes left in sector, lesser of the two. */
      off_t inode_left = inode->max_read_length - offset;
      int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
      int min_left = inode_left < sector_left ? inode_left : sector_left;

      /* Number of bytes to actually copy out of this sector. */
      int chunk_size = size < min_left ? size : min_left;
      if (chunk_size <= 0)
        break;


      cached_block = cache_insert (sector_idx);


      cached_block->active_r_w ++ ;
      lock_release (&cached_block->lock);



      thread_current ()->cache_block_being_accessed = cached_block;
      memcpy (buffer + bytes_read, cached_block->data + sector_ofs, chunk_size);
      cached_block->accessed = true;

      thread_current ()->cache_block_being_accessed = NULL;

      lock_acquire (&cached_block->lock);
      cached_block->active_r_w --;
      if (cached_block->active_r_w == 0)
        cond_broadcast (&cached_block->r_w_done, &cached_block->lock);
      lock_release (&cached_block->lock);


      
      /* Advance. */
      size -= chunk_size;
      offset += chunk_size;
      bytes_read += chunk_size;

    }
    if (((int)sector_idx != -1) && (bytes_to_sectors (inode->max_read_length) > sector_idx))
    {
      block_sector_t next_sector = byte_to_sector (inode, offset + BLOCK_SECTOR_SIZE);
      cache_read_ahead (next_sector);
    }


  return bytes_read;
}
Пример #29
0
void inode_release_allocated_sectors (struct inode *inode, int num_blocks_to_remove)
{
  int indirect_block_num;
  int final_block_index;
  block_sector_t ind_block_buf[BLOCKS_PER_INDIRECT];
  block_sector_t db_ind_block_buf[BLOCKS_PER_INDIRECT];


  int block_num;
  int original_inode_sectors = bytes_to_sectors (inode->length);
  int new_sectors = original_inode_sectors - num_blocks_to_remove;

  //initialize block buffers based on current number of sectors
  if (inode->doubly_indirect_block != 0)
  {
    block_read (fs_device, inode->doubly_indirect_block, db_ind_block_buf);
    indirect_block_num = ( original_inode_sectors - (NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT )) / BLOCKS_PER_INDIRECT;
    block_read (fs_device, db_ind_block_buf[indirect_block_num], ind_block_buf);
  }
  else 
  {
    memset (db_ind_block_buf, 0, sizeof db_ind_block_buf);
    
    if (inode->indirect_block != 0)
      block_read (fs_device, inode->indirect_block, ind_block_buf);
    else
      memset (ind_block_buf, 0, sizeof ind_block_buf);
  }



  for (block_num = original_inode_sectors - 1 ; block_num >= new_sectors; block_num --)
  {
    if (block_num >= NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT)
    {
      indirect_block_num = ( block_num - (NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT )) / BLOCKS_PER_INDIRECT;
      final_block_index = ( block_num - (NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT )) % BLOCKS_PER_INDIRECT;

      if ((final_block_index == BLOCK_SECTOR_SIZE - 1) 
          && (indirect_block_num != BLOCK_SECTOR_SIZE -1)
          && (db_ind_block_buf[indirect_block_num + 1] != 0))
        // free previous indirect block, read in current indirect block
      {
        block_read (fs_device, db_ind_block_buf[indirect_block_num], ind_block_buf);
        free_map_release (db_ind_block_buf[indirect_block_num + 1], 1);
        db_ind_block_buf[indirect_block_num + 1] = 0;
      }
      free_map_release (ind_block_buf[final_block_index], 1);
      continue;
       
    }
    if ((block_num < NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT)
      && (block_num >= NUM_DIRECT_BLOCKS))
      //single indirect block now
    {
      final_block_index = block_num - NUM_DIRECT_BLOCKS;
      if ((final_block_index == BLOCK_SECTOR_SIZE -1)
        && (inode->doubly_indirect_block != 0))
      {
        free_map_release (db_ind_block_buf[0], 1);
        free_map_release (inode->doubly_indirect_block, 1);
        inode->doubly_indirect_block = 0;
        block_read (fs_device, inode->indirect_block, ind_block_buf);
      }
      free_map_release (ind_block_buf[final_block_index], 1);
      continue;
    }
    if (block_num < NUM_DIRECT_BLOCKS)
      //onto direct blocks now
    {
      if ((block_num == NUM_DIRECT_BLOCKS -1)
        && (inode->indirect_block != 0))
        {
          free_map_release (inode->indirect_block, 1);
          inode->indirect_block = 0;
        }
      free_map_release (inode->direct_blocks[block_num], 1);
      continue;
    }
  }


  //rewrite doubly indirect block to disk
  // this is necessary because inode_extend relies on 
  // entries being null
  if (inode->doubly_indirect_block != 0)
  {
    block_write (fs_device, inode->doubly_indirect_block, db_ind_block_buf);
  }
}
Пример #30
0
bool 
inode_extend (struct inode *inode, int num_blocks_to_add)
{
  ASSERT (num_blocks_to_add >= 0);

  block_sector_t ind_block_buf[BLOCKS_PER_INDIRECT];
  block_sector_t db_ind_block_buf[BLOCKS_PER_INDIRECT];
  static char zeros[BLOCK_SECTOR_SIZE];
  bool success = true;

  int indirect_block_num = 0;
  int final_block_index = 0;

  size_t original_inode_sectors = bytes_to_sectors (inode_length (inode));
  size_t new_sectors = original_inode_sectors + num_blocks_to_add;


  //initialize block buffers based on current number of sectors
  if (inode->doubly_indirect_block != 0)
  {
    block_read (fs_device, inode->doubly_indirect_block, db_ind_block_buf);
    indirect_block_num = ( original_inode_sectors - (NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT )) / BLOCKS_PER_INDIRECT;
    block_read (fs_device, db_ind_block_buf[indirect_block_num], ind_block_buf);
  }
  else 
  {
    memset (db_ind_block_buf, 0, sizeof db_ind_block_buf);
    
    if (inode->indirect_block != 0)
      block_read (fs_device, inode->indirect_block, ind_block_buf);
    else
      memset (ind_block_buf, 0, sizeof ind_block_buf);
  }



  size_t block_num;
  block_sector_t sector;
  for (block_num = original_inode_sectors; block_num < new_sectors; block_num ++)
  {
    if (free_map_allocate (1, &sector))
    {
        if (block_num < NUM_DIRECT_BLOCKS)
        {
          inode->direct_blocks[block_num] = sector;
          block_write (fs_device, sector, zeros);
          continue;
        }
        if (block_num == NUM_DIRECT_BLOCKS && inode->indirect_block == 0)
          //allocate indirect block
        {
          inode->indirect_block = sector;
          block_write (fs_device, sector, zeros);
          block_num --;
          continue;
        }
        if (block_num < NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT)
        {

          ind_block_buf[block_num - NUM_DIRECT_BLOCKS] = sector;
          block_write (fs_device, sector, zeros);

          if ((block_num == new_sectors - 1) || (block_num == NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT - 1)) 
          //last block or end of indirect block
          {
            block_write (fs_device, inode->indirect_block, ind_block_buf);
            memset (ind_block_buf, 0, BLOCK_SECTOR_SIZE);
          }
          continue;
        }
        
        if ((block_num == NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT)
            && inode->doubly_indirect_block == 0)
          // allocate doubly indirect block
        {
            inode->doubly_indirect_block = sector;
            block_write (fs_device, sector, zeros);
            block_num -- ;
            continue;
        }
        if (block_num >= NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT)
        {
          indirect_block_num = ( block_num - (NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT )) / BLOCKS_PER_INDIRECT;
          final_block_index = ( block_num - (NUM_DIRECT_BLOCKS + BLOCKS_PER_INDIRECT )) % BLOCKS_PER_INDIRECT;

          if ((final_block_index == 0) && 
              (db_ind_block_buf[indirect_block_num] == 0))// new indirect block
          {
            db_ind_block_buf[indirect_block_num] = sector;
            block_write (fs_device, sector, zeros);
            block_num--;
            continue;
          }
          ind_block_buf[final_block_index] = sector;
          block_write (fs_device, sector, zeros);

          if ((block_num == new_sectors - 1) || (final_block_index == BLOCKS_PER_INDIRECT - 1)) 
          //last block or end of indirect block
          {
            block_write (fs_device, db_ind_block_buf[indirect_block_num], ind_block_buf);
            memset (ind_block_buf, 0, BLOCK_SECTOR_SIZE);
          }
          if ((block_num == new_sectors - 1) ) 
          //last block 
          {
            block_write (fs_device, inode->doubly_indirect_block, db_ind_block_buf);
            memset (db_ind_block_buf, 0, BLOCK_SECTOR_SIZE);
          } 
        }
    }
    else
    {
      success = false;


      //write all outstanding buffers to disk.
      // This makes rolling back easier
      if (inode->indirect_block !=0)
      {
        if (inode->doubly_indirect_block !=0)
        {
          block_write (fs_device, db_ind_block_buf[indirect_block_num], ind_block_buf);
          block_write (fs_device, inode->doubly_indirect_block, db_ind_block_buf);
        }
        else
        {
          block_write (fs_device, inode->indirect_block, ind_block_buf);
        }
      }
      break;
    }
  }

  if (success == false) //allocation fails along the way, roll back allocations
  {
    inode_release_allocated_sectors (inode, original_inode_sectors);
  }

  return success;

}