====================================
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对程序出错后的处理。