Ext2索引节点分配

文件在磁盘的存储不同于程序员所看到的文件,主要表现在两个方面:块可以分散在磁盘上(尽管文件系统尽力保持块连续存放以提高访问速度),以及程序员看到的文件似乎比实际的文件大,这是因为程序可以把洞引人文件(通过lseek ()系统调用)。

 

从本篇博文开始,我们将介绍Ext2文件系统如何管理磁盘空间,也就是说,如何分配和释放索引节点和数据块。有两个主要的问题必须考虑:

 

(1)空间管理必须尽力避免文件碎片,也就是说,避免文件在物理上存放于几个小的、不相邻的盘块上。文件碎片增加了对文件的连续读操作的平均时间,因为在读操作期间,磁头必须频繁地重新定位。这个问题类似于在内存管理中的“伙伴系统算法”博文中所讨论的RAM的外部碎片问题。
   
(2)空间管理必须考虑效率,也就是说,内核应该能从文件的偏移量快速地导出Ext2分区上相应的逻辑块号。为了达到此目的,内核应该尽可能地限制对磁盘上寻址表的访问次数,因为对该表的访问会极大地增加文件的平均访问时间。

 

 

1 创建索引节点

 

 

ext2_new_inode()函数创建Ext2磁盘的索引节点,返回相应的索引节点对象的地址(或失败时为NULL)。该函数谨慎地选择存放该新索引节点的块组;它将无联系的目录散放在不同的组,而且同时把文件存放在父目录的同一组。为了平衡普通文件数与块组中的目录数,Ext2为每一个块组引入“债(debt) ”参数。

 

ext2_new_inode函数有两个参数:dir,所创建索引节点父目录对应的索引节点对象的地址,新创建的索引节点必须插入到这个目录中,成为其中的一个目录项;mode,要创建的索引节点的类型。后一个参数还包含一个MS_SYNCHRONOUS标志,该标志请求当前进程一直挂起,直到索引节点被分配成功或失败。该函数代码如下:


struct inode *ext2_new_inode(struct inode *dir, int mode)
{
      struct super_block *sb;
      struct buffer_head *bitmap_bh = NULL;
      struct buffer_head *bh2;
      int group, i;
      ino_t ino = 0;
      struct inode * inode;
      struct ext2_group_desc *gdp;
      struct ext2_super_block *es;
      struct ext2_inode_info *ei;
      struct ext2_sb_info *sbi;
      int err;

      sb = dir->i_sb;
      inode = new_inode(sb);
      if (!inode)
            return ERR_PTR(-ENOMEM);

      ei = EXT2_I(inode);
      sbi = EXT2_SB(sb);
      es = sbi->s_es;
      if (S_ISDIR(mode)) {
            if (test_opt(sb, OLDALLOC))
                  group = find_group_dir(sb, dir);
            else
                  group = find_group_orlov(sb, dir);
      } else
            group = find_group_other(sb, dir);

      if (group == -1) {
            err = -ENOSPC;
            goto fail;
      }

      for (i = 0; i < sbi->s_groups_count; i++) {
            gdp = ext2_get_group_desc(sb, group, &bh2);
            brelse(bitmap_bh);
            bitmap_bh = read_inode_bitmap(sb, group);
            if (!bitmap_bh) {
                  err = -EIO;
                  goto fail;
            }
            ino = 0;

repeat_in_this_group:
            ino = ext2_find_next_zero_bit((unsigned long *)bitmap_bh->b_data,
                                    EXT2_INODES_PER_GROUP(sb), ino);
            if (ino >= EXT2_INODES_PER_GROUP(sb)) {
                  /*
                   * Rare race: find_group_xx() decided that there were
                   * free inodes in this group, but by the time we tried
                   * to allocate one, they're all gone.  This can also
                   * occur because the counters which find_group_orlov()
                   * uses are approximate.  So just go and search the
                   * next block group.
                   */
                  if (++group == sbi->s_groups_count)
                        group = 0;
                  continue;
            }
            if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group),
                                    ino, bitmap_bh->b_data)) {
                  /* we lost this inode */
                  if (++ino >= EXT2_INODES_PER_GROUP(sb)) {
                        /* this group is exhausted, try next group */
                        if (++group == sbi->s_groups_count)
                              group = 0;
                        continue;
                  }
                  /* try to find free inode in the same group */
                  goto repeat_in_this_group;
            }
            goto got;
      }

      /*
       * Scanned all blockgroups.
       */
      err = -ENOSPC;
      goto fail;
got:
      mark_buffer_dirty(bitmap_bh);
      if (sb->s_flags & MS_SYNCHRONOUS)
            sync_dirty_buffer(bitmap_bh);
      brelse(bitmap_bh);

      ino += group * EXT2_INODES_PER_GROUP(sb) + 1;
      if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
            ext2_error (sb, "ext2_new_inode",
                      "reserved inode or inode > inodes count - "
                      "block_group = %d,inode=%lu", group,
                      (unsigned long) ino);
            err = -EIO;
            goto fail;
      }

      percpu_counter_mod(&sbi->s_freeinodes_counter, -1);
      if (S_ISDIR(mode))
            percpu_counter_inc(&sbi->s_dirs_counter);

      spin_lock(sb_bgl_lock(sbi, group));
      gdp->bg_free_inodes_count =
                cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
      if (S_ISDIR

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值