EXT2超级块初始化(一)

 

====================================
static int ext2_get_sb(struct file_system_type *fs_type,
 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
 return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt);
}
get_sb_bdev()是VFS函数分配并初始化一个新的适合于磁盘文件系统的超级块;它接收ext2_file_super()函数的地址,该函数从Ext2磁盘分区读取磁盘超级块。
int get_sb_bdev(struct file_system_type *fs_type,
 int flags, const char *dev_name, void *data,
 int (*fill_super)(struct super_block *, void *, int),
 struct vfsmount *mnt)
{
01 struct block_device *bdev;
02 struct super_block *s;
03 fmode_t mode = FMODE_READ;
04 int error = 0;
05 if (!(flags & MS_RDONLY))
06  mode |= FMODE_WRITE;
07 bdev = open_bdev_exclusive(dev_name, mode, fs_type);
08 if (IS_ERR(bdev))
09  return PTR_ERR(bdev);
10 down(&bdev->bd_mount_sem);
11 s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
12 up(&bdev->bd_mount_sem);
13 if (IS_ERR(s))
14  goto error_s;
15 if (s->s_root) {
16  if ((flags ^ s->s_flags) & MS_RDONLY) {
17   deactivate_locked_super(s);
18   error = -EBUSY;
19   goto error_bdev;
20  }
21
22  close_bdev_exclusive(bdev, mode);
23 } else {
24  char b[BDEVNAME_SIZE];
25
26  s->s_flags = flags;
27  s->s_mode = mode;
28  strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
29  sb_set_blocksize(s, block_size(bdev));
30  error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
31  if (error) {
32   deactivate_locked_super(s);
33   goto error;
34  }
35
36  s->s_flags |= MS_ACTIVE;
37  bdev->bd_super = s;
38 }
39
40 simple_set_mnt(mnt, s);
41 return 0;
42
43error_s:
44 error = PTR_ERR(s);
45error_bdev:
46 close_bdev_exclusive(bdev, mode);
47error:
48 return error;
49}
对于常规的文件系统,参数dev_name必须是一个有效的路径名。
第7行调用open_bdev_excl()打开设备文件名为dev_name的块设备
第11行调用sget()函数搜索文件系统的超级块对象链表,如果找到一个块设备相关的超级块,则返回它的地址。否则,分配并初始化一个新的超级块对象,把它插入到文件系统链表和超级块全局链表中,并返回其地址。
第15行如果为真,则返回新超级块对象的地址
第23行否则,把参数flags中的值拷贝到超级块的s_flags字段
第28行对s_id字段设置合适的值
第29行设置s_blocksize的的大小,可以为1024、2048、4096等。
第30行调用依赖文件系统的函数fill_super访问磁盘上的超级块信息,并填充新超级块对象的其它字段
第41行成功返回。

======================================
static int ext2_fill_super(struct super_block *sb, void *data, int silent)
{
001 struct buffer_head * bh;
002 struct ext2_sb_info * sbi;
003 struct ext2_super_block * es;
004 struct inode *root;
005 unsigned long block;
006 unsigned long sb_block = get_sb_block(&data);
007 unsigned long logic_sb_block;
008 unsigned long offset = 0;
009 unsigned long def_mount_opts;
010 long ret = -EINVAL;
011 int blocksize = BLOCK_SIZE;
012 int db_count;
013 int i, j;
014 __le32 features;
015 int err;
第1行定义缓存区头部描述符
第2行定义一个超级块数据,不过这个是在内存中
第3行buffer中的超级块描述符
第4行根目录结点描述述
第6行
第11行块的大小
017 sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
018 if (!sbi)
019  return -ENOMEM;
020
021 sbi->s_blockgroup_lock =
022  kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
023 if (!sbi->s_blockgroup_lock) {
024  kfree(sbi);
025  return -ENOMEM;
026 }
027 sb->s_fs_info = sbi;
028 sbi->s_sb_block = sb_block;
029
030 blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
031 if (!blocksize) {
032  printk ("EXT2-fs: unable to set blocksize\n");
033  goto failed_sbi;
034 }
035 if (blocksize != BLOCK_SIZE) {
036  logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
037  offset = (sb_block*BLOCK_SIZE) % blocksize;
038 } else {
039  logic_sb_block = sb_block;
040 }
041
042 if (!(bh = sb_bread(sb, logic_sb_block))) {
043  printk ("EXT2-fs: unable to read superblock\n");
044  goto failed_sbi;
045 }
第17行使用kzalloc函数在内核上分配空间,注意里面的第二个参数,其实它是kmalloc的函数,然后以0对它时行初始化。
第18行对在内存中的超级块文件系统的s_blockgroup_lock进行分配空间。
第27行超级块中的sbi字段指向,在内存中的文件系统的超级块数据。
第30行使用sb_min_blocksize函数在块设备的块大小和目前使用的块大小比较,使用较小的,有可能块设备的扇区比默认使用的块要大。
第35行如果块的大小和默认的块大小不等,逻辑的块就等于得到的块乘以默认的块再除刚才使用sb_min_blocksize函数得到的块的大小。偏移取模
第39行否则的话直接把它赋给逻辑块大小。
第42行使用sb_bread函数得到某个特殊块的缓存区头部来赋给当前的缓存区头部描述符。
050 es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
051 sbi->s_es = es;
052 sb->s_magic = le16_to_cpu(es->s_magic);
054 if (sb->s_magic != EXT2_SUPER_MAGIC)
055  goto cantfind_ext2;
058 def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
059 if (def_mount_opts & EXT2_DEFM_DEBUG)
060  set_opt(sbi->s_mount_opt, DEBUG);
061 if (def_mount_opts & EXT2_DEFM_BSDGROUPS)
062  set_opt(sbi->s_mount_opt, GRPID);
063 if (def_mount_opts & EXT2_DEFM_UID16)
064  set_opt(sbi->s_mount_opt, NO_UID32);
065#ifdef CONFIG_EXT2_FS_XATTR
066 if (def_mount_opts & EXT2_DEFM_XATTR_USER)
067  set_opt(sbi->s_mount_opt, XATTR_USER);
068#endif
069#ifdef CONFIG_EXT2_FS_POSIX_ACL
070 if (def_mount_opts & EXT2_DEFM_ACL)
071  set_opt(sbi->s_mount_opt, POSIX_ACL);
072#endif
第50行通过缓存区头部的data字段和偏移,计算出在缓存区中超级块的地址。
第51行使用sbi的s_es字段来指向这个描述符
第52行超级块的魔数,le16_to_cpu这个函数是解决大小端的问题
第54行这个魔数和系统给的,不相等,就会报出错误

074 if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
075  set_opt(sbi->s_mount_opt, ERRORS_PANIC);
076 else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
077  set_opt(sbi->s_mount_opt, ERRORS_CONT);
078 else
079  set_opt(sbi->s_mount_opt, ERRORS_RO);
080
081 sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
082 sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
083 
084 set_opt(sbi->s_mount_opt, RESERVATION);
085
086 if (!parse_options ((char *) data, sbi))
087  goto failed_mount;
088
089 sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
090  ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
091   MS_POSIXACL : 0);
093 ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
094        EXT2_MOUNT_XIP if not */
096 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
097     (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
098      EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
099      EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U)))
100  printk("EXT2-fs warning: feature flags set on rev 0 fs, "
101         "running e2fsck is recommended\n");
102 features=EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_SUPP);
103 if (features) {
104  printk("EXT2-fs: %s: couldn't mount because of "
105         "unsupported optional features (%x).\n",
106         sb->s_id, le32_to_cpu(features));
107  goto failed_mount;
108 }
109 if (!(sb->s_flags & MS_RDONLY) &&
110     (features=EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
111  printk("EXT2-fs: %s: couldn't mount RDWR because of "
112         "unsupported optional features (%x).\n",
113         sb->s_id, le32_to_cpu(features));
114  goto failed_mount;
115 }
第81行把内存中的超级块中的uid字段赋给ext2文件系统描述符的s_resuid字段
第82行把内存中的超级块中的gid字段赋给ext2文件系统描述符的s_resgid字段
第89行设置sb的标志,其中MS_POSIXACL为posix系统的访问控制表。
第96行判断版本的等级
117 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
118
119 if (ext2_use_xip(sb) && blocksize != PAGE_SIZE) {
120  if (!silent)
121   printk("XIP: Unsupported blocksize\n");
122  goto failed_mount;
123 }
124
125 /* If the blocksize doesn't match, re-read the thing.. */
126 if (sb->s_blocksize != blocksize) {
127  brelse(bh);
128
129  if (!sb_set_blocksize(sb, blocksize)) {
130   printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n");
131   goto failed_sbi;
132  }
133
134  logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
135  offset = (sb_block*BLOCK_SIZE) % blocksize;
136  bh = sb_bread(sb, logic_sb_block);
137  if(!bh) {
138   printk("EXT2-fs: Couldn't read superblock on "
139          "2nd try.\n");
140   goto failed_sbi;
141  }
142  es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
143  sbi->s_es = es;
144  if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
145   printk ("EXT2-fs: Magic mismatch, very weird !\n");
146   goto failed_mount;
147  }
148 }
150 sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
第117行得到块的大小
第126行如果块的大小和sb字段的块大小不相等,重新再设置一次
第127减小对缓存区头部的引用
第129行设置sb块的大小。
第134行计算逻辑块的大小
第135行计算出偏移
第136行使用sb_bread函数得到缓存区头部,来初始化bh指针。
第142行得到内存中的超级块es
第143行文件描述的s_es指向这个超级块。
第150行使用ext2_max_size函数计算出最大的字节。
152 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
153  sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
154  sbi->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
155 } else {
156  sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
157  sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
158  if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) ||
159      !is_power_of_2(sbi->s_inode_size) ||
160      (sbi->s_inode_size > blocksize)) {
161   printk ("EXT2-fs: unsupported inode size: %d\n",
162    sbi->s_inode_size);
163   goto failed_mount;
164  }
165 }
主要判断一下超级块的版本等级。如果没有达到,就对文件系统描述的s_indoe_size字段、s_first_ino进行初始化。
167 sbi->s_frag_size = EXT2_MIN_FRAG_SIZE <<
168       le32_to_cpu(es->s_log_frag_size);
169 if (sbi->s_frag_size == 0)
170  goto cantfind_ext2;
171 sbi->s_frags_per_block = sb->s_blocksize / sbi->s_frag_size;
172
173 sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
174 sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
175 sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
176
177 if (EXT2_INODE_SIZE(sb) == 0)
178  goto cantfind_ext2;
179 sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb);
180 if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0)
181  goto cantfind_ext2;
182 sbi->s_itb_per_group = sbi->s_inodes_per_group /
183     sbi->s_inodes_per_block;
184 sbi->s_desc_per_block = sb->s_blocksize /
185     sizeof (struct ext2_group_desc);
186 sbi->s_sbh = bh;
187 sbi->s_mount_state = le16_to_cpu(es->s_state);
188 sbi->s_addr_per_block_bits =
189  ilog2 (EXT2_ADDR_PER_BLOCK(sb));
190 sbi->s_desc_per_block_bits =
191  ilog2 (EXT2_DESC_PER_BLOCK(sb));
192
193 if (sb->s_magic != EXT2_SUPER_MAGIC)
194  goto cantfind_ext2;
195
196 if (sb->s_blocksize != bh->b_size) {
197  if (!silent)
198   printk ("VFS: Unsupported blocksize on dev "
199    "%s.\n", sb->s_id);
200  goto failed_mount;
201 }
第167行给sbi段的大小赋值
第171行给sbi中每块中的片数赋值
第173-175行给每组中块、每组中的片、每组的节点进行赋值
第179行给每块中的节点赋值
第184行给每块中组描述符赋值
第186行sbi中的s_sbh指针目前的缓存区头部bh
第187行挂载状态
第193行查看魔数是否相等。
203 if (sb->s_blocksize != sbi->s_frag_size) {
204  printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
205   sbi->s_frag_size, sb->s_blocksize);
206  goto failed_mount;
207 }
208
209 if (sbi->s_blocks_per_group > sb->s_blocksize * 8) {
210  printk ("EXT2-fs: #blocks per group too big: %lu\n",
211   sbi->s_blocks_per_group);
212  goto failed_mount;
213 }
214 if (sbi->s_frags_per_group > sb->s_blocksize * 8) {
215  printk ("EXT2-fs: #fragments per group too big: %lu\n",
216   sbi->s_frags_per_group);
217  goto failed_mount;
218 }
219 if (sbi->s_inodes_per_group > sb->s_blocksize * 8) {
220  printk ("EXT2-fs: #inodes per group too big: %lu\n",
221   sbi->s_inodes_per_group);
222  goto failed_mount;
223 }
对块的大小、每组中的块、每组中的片、每组中的节点进行判断。如果判断条件为真,进行相应的处理。
225 if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
226  goto cantfind_ext2;
227  sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
228     le32_to_cpu(es->s_first_data_block) - 1)
229      / EXT2_BLOCKS_PER_GROUP(sb)) + 1;
230 db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
231     EXT2_DESC_PER_BLOCK(sb);
232 sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
233 if (sbi->s_group_desc == NULL) {
234  printk ("EXT2-fs: not enough memory\n");
235  goto failed_mount;
236 }
237 bgl_lock_init(sbi->s_blockgroup_lock);
238 sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL);
239 if (!sbi->s_debts) {
240  printk ("EXT2-fs: not enough memory\n");
241  goto failed_mount_group_desc;
242 }
243 for (i = 0; i < db_count; i++) {
244  block = descriptor_loc(sb, logic_sb_block, i);
245  sbi->s_group_desc[i] = sb_bread(sb, block);
246  if (!sbi->s_group_desc[i]) {
247   for (j = 0; j < i; j++)
248    brelse (sbi->s_group_desc[j]);
249   printk ("EXT2-fs: unable to read group descriptors\n");
250   goto failed_mount_group_desc;
251  }
252 }
253 if (!ext2_check_descriptors (sb)) {
254  printk ("EXT2-fs: group descriptors corrupted!\n");
255  goto failed_mount2;
256 }
第227行对sbi的组数进行赋值
第232行对组描述符分配空间
第243行循环对sbi中的s_group_dec数组进行赋值。
257 sbi->s_gdb_count = db_count;
258 get_random_bytes(&sbi->s_next_generation, sizeof(u32));
259 spin_lock_init(&sbi->s_next_gen_lock);
260 spin_lock_init(&sbi->s_rsv_window_lock);
261 sbi->s_rsv_window_root = RB_ROOT;
262
263 sbi->s_rsv_window_head.rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
264 sbi->s_rsv_window_head.rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
265 sbi->s_rsv_window_head.rsv_alloc_hit = 0;
266 sbi->s_rsv_window_head.rsv_goal_size = 0;
267 ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);
分别对sbi中的s_gdb_count赋值,s_rsv_window_root赋值。
269 err = percpu_counter_init(&sbi->s_freeblocks_counter,
270    ext2_count_free_blocks(sb));
271 if (!err) {
272  err = percpu_counter_init(&sbi->s_freeinodes_counter,
273    ext2_count_free_inodes(sb));
274 }
275 if (!err) {
276  err = percpu_counter_init(&sbi->s_dirs_counter,
277    ext2_count_dirs(sb));
278 }
279 if (err) {
280  printk(KERN_ERR "EXT2-fs: insufficient memory\n");
281  goto failed_mount3;
282 }
283 sb->s_op = &ext2_sops;
284 sb->s_export_op = &ext2_export_ops;
285 sb->s_xattr = ext2_xattr_handlers;
286 root = ext2_iget(sb, EXT2_ROOT_INO);
287 if (IS_ERR(root)) {
288  ret = PTR_ERR(root);
289  goto failed_mount3;
290 }
291 if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
292  iput(root);
293  printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
294  goto failed_mount3;
295 }
296
297 sb->s_root = d_alloc_root(root);
298 if (!sb->s_root) {
299  iput(root);
300  printk(KERN_ERR "EXT2-fs: get root inode failed\n");
301  ret = -ENOMEM;
302  goto failed_mount3;
303 }
304 if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
305  ext2_warning(sb, __func__,
306   "mounting ext3 filesystem as ext2");
307 ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
308 return 0;
第283行使sb的操作文件指向ext2_sops的操作方法
第286行使用ext2_iget方法得到根目录的节点,并对其它进行初始化
第297行对sb的根目录进行初始化。
310cantfind_ext2:
311 if (!silent)
312  printk("VFS: Can't find an ext2 filesystem on dev %s.\n",
313         sb->s_id);
314 goto failed_mount;
315failed_mount3:
316 percpu_counter_destroy(&sbi->s_freeblocks_counter);
317 percpu_counter_destroy(&sbi->s_freeinodes_counter);
318 percpu_counter_destroy(&sbi->s_dirs_counter);
319failed_mount2:
320 for (i = 0; i < db_count; i++)
321  brelse(sbi->s_group_desc[i]);
322failed_mount_group_desc:
323 kfree(sbi->s_group_desc);
324 kfree(sbi->s_debts);
325failed_mount:
326 brelse(bh);
327failed_sbi:
328 sb->s_fs_info = NULL;
329 kfree(sbi);
330 return ret;
331}
第310-330对程序出错后的处理。

你可能感兴趣的:(linux,文件系统)