Beispiel #1
0
/* 回收inode的数据块和inode本身 */
void inode_release(struct partition* part, uint32_t inode_no) {
   struct inode* inode_to_del = inode_open(part, inode_no);
   ASSERT(inode_to_del->i_no == inode_no);

/* 1 回收inode占用的所有块 */
   uint8_t block_idx = 0, block_cnt = 12;
   uint32_t block_bitmap_idx;
   uint32_t all_blocks[140] = {0};	  //12个直接块+128个间接块

   /* a 先将前12个直接块存入all_blocks */
   while (block_idx < 12) {
      all_blocks[block_idx] = inode_to_del->i_sectors[block_idx];
      block_idx++;
   }

   /* b 如果一级间接块表存在,将其128个间接块读到all_blocks[12~], 并释放一级间接块表所占的扇区 */
   if (inode_to_del->i_sectors[12] != 0) {
      ide_read(part->my_disk, inode_to_del->i_sectors[12], all_blocks + 12, 1);
      block_cnt = 140;

      /* 回收一级间接块表占用的扇区 */
      block_bitmap_idx = inode_to_del->i_sectors[12] - part->sb->data_start_lba;
      ASSERT(block_bitmap_idx > 0);
      bitmap_set(&part->block_bitmap, block_bitmap_idx, 0);
      bitmap_sync(cur_part, block_bitmap_idx, BLOCK_BITMAP);
   }
   
   /* c inode所有的块地址已经收集到all_blocks中,下面逐个回收 */
   block_idx = 0;
   while (block_idx < block_cnt) {
      if (all_blocks[block_idx] != 0) {
	 block_bitmap_idx = 0;
	 block_bitmap_idx = all_blocks[block_idx] - part->sb->data_start_lba;
	 ASSERT(block_bitmap_idx > 0);
	 bitmap_set(&part->block_bitmap, block_bitmap_idx, 0);
	 bitmap_sync(cur_part, block_bitmap_idx, BLOCK_BITMAP);
      }
      block_idx++; 
   }

/*2 回收该inode所占用的inode */
   bitmap_set(&part->inode_bitmap, inode_no, 0);  
   bitmap_sync(cur_part, inode_no, INODE_BITMAP);

   /******     以下inode_delete是调试用的    ******
   * 此函数会在inode_table中将此inode清0,
   * 但实际上是不需要的,inode分配是由inode位图控制的,
   * 硬盘上的数据不需要清0,可以直接覆盖*/
   void* io_buf = sys_malloc(1024);
   inode_delete(part, inode_no, io_buf);
   sys_free(io_buf);
   /***********************************************/
    
   inode_close(inode_to_del);
}
Beispiel #2
0
void inode_delete(disk_sector_t sector){
  struct inode_disk *disk_inode;
  disk_inode = calloc (1, sizeof *disk_inode);
  if(disk_inode != NULL){
    cache_read(sector, disk_inode, 0, DISK_SECTOR_SIZE);
    if(disk_inode->level == 0)
      free_map_release(disk_inode->inode_index, disk_inode->count);
    else{
      size_t i;
      for(i=0;i<disk_inode->count;i++)
        inode_delete(disk_inode->inode_index[i]);
    }
    free(disk_inode);
  }
  free_map_release(&sector, 1);
}
Beispiel #3
0
/**
 * bg_lower_ilevel - lower the index level
 * @new_low: the first index item in the second lowest level
 * @ptst: per-thread state
 *
 * Note: the lowest index level is removed by nullifying
 * the reference to the lowest level from the second lowest level.
 */
void bg_lower_ilevel(inode_t *new_low, ptst_t *ptst)
{
        inode_t *old_low = new_low->down;

        /* remove the lowest index level */
        while (NULL != new_low) {
                new_low->down = NULL;
                --new_low->node->level;
                new_low = new_low->right;
        }

        /* garbage collect the old low level */
        while (NULL != old_low) {
                inode_delete(old_low, ptst);
                old_low = old_low->right;
        }
}
Beispiel #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;
  bool flag = inode->sector == 4023;
  /* 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) 
        {
          inode_delete(inode->sector);
        }

      free (inode); 
    }
}
Beispiel #5
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, int level, bool is_dir)
{
  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->magic = INODE_MAGIC;
    disk_inode->level = level;
    disk_inode->is_dir = is_dir;
    if(level == 0){ // direct
      disk_inode->count = sectors;
      if (free_map_allocate (sectors, disk_inode->inode_index)){
        cache_write (sector, disk_inode, 0, DISK_SECTOR_SIZE);
        static char zeros[DISK_SECTOR_SIZE];
        size_t i;

        for (i = 0; i < disk_inode->count; i++) 
          cache_write (disk_inode->inode_index[i], zeros, 0, DISK_SECTOR_SIZE); 
        success = true; 
      } 
    }
    else if(level == 1){ // sigle indirect
      disk_inode->count = DIV_ROUND_UP(sectors, DIRECT_INODE);
      if(free_map_allocate (disk_inode->count, disk_inode->inode_index)){
        size_t size;
        int i;
        for (i = 0; i < disk_inode->count; i++){
          size = sectors - DIRECT_INODE*i;
          if(size > DIRECT_INODE)
            size = DIRECT_INODE;
          if(!inode_create(disk_inode->inode_index[i], size*DISK_SECTOR_SIZE, level-1, is_dir)){
            success = false;
            for(i=i-1;i>=0;i--)
              inode_delete(disk_inode->inode_index[i]);
            break;
          }
        }
        if(i == disk_inode->count){
          cache_write (sector, disk_inode, 0, DISK_SECTOR_SIZE);
          success = true; 
        }
      }
    }
    else{ // double indirect
      disk_inode->count = DIV_ROUND_UP(sectors, DIRECT_INODE * SINGLE_INDIRECT_INODE);
      if(free_map_allocate (disk_inode->count, disk_inode->inode_index)){
        size_t size;
        int i;
        for (i = 0; i < disk_inode->count; i++){
          size = sectors-DIRECT_INODE*SINGLE_INDIRECT_INODE*i;
          if(size > SINGLE_INDIRECT_INODE * DIRECT_INODE)
            size = SINGLE_INDIRECT_INODE * DIRECT_INODE;
          if(!inode_create(disk_inode->inode_index[i], size*DISK_SECTOR_SIZE, level-1, is_dir)){
            success = false;
            for(i=i-1;i>=0;i--)
              inode_delete(disk_inode->inode_index[i]);
            break;
          }
        }
        if(i == disk_inode->count){
          cache_write (sector, disk_inode, 0, DISK_SECTOR_SIZE);
          success = true; 
        }
      }
    }

    free (disk_inode);
  }
  return success;
}