1. super.c
1 /*
2 * linux/fs/super.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * super.c contains code to handle the super-block tables.
9 */
10 #include <linux/config.h>
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <asm/system.h>
14
15 #include <errno.h>
16 #include <sys/stat.h>
2 * linux/fs/super.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * super.c contains code to handle the super-block tables.
9 */
10 #include <linux/config.h>
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <asm/system.h>
14
15 #include <errno.h>
16 #include <sys/stat.h>
18 int sync_dev(int dev);
19 void wait_for_keypress(void);
20
21 /* set_bit uses setb, as gas doesn't recognize setc */
22 #define set_bit(bitnr,addr) ({ \
23 register int __res __asm__("ax"); \
24 __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
25 __res; })
bt 功能:按照源操作指定的位号,测试目的操作数,当指令执行时,被测试位的状态被复制到进位标志CF
19 void wait_for_keypress(void);
20
21 /* set_bit uses setb, as gas doesn't recognize setc */
22 #define set_bit(bitnr,addr) ({ \
23 register int __res __asm__("ax"); \
24 __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
25 __res; })
bt 功能:按照源操作指定的位号,测试目的操作数,当指令执行时,被测试位的状态被复制到进位标志CF
在asm语句中对硬件寄存器的引用必须用“%%”
如果CF为1,setb就会置位后面的寄存器。因此这里就是测试addr开始内存处第bitnr位是1还是0
27 struct super_block super_block[NR_SUPER];
28 /* this is initialized in init/main.c */
29 int ROOT_DEV = 0;
init/main.c:60:#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
init/main.c:110: ROOT_DEV = ORIG_ROOT_DEV;
这里的ORIG_ROOT_DEV是在init/main中通过询问BIOS获得并保存的。
init/main.c:110: ROOT_DEV = ORIG_ROOT_DEV;
这里的ORIG_ROOT_DEV是在init/main中通过询问BIOS获得并保存的。
31 static void lock_super(struct super_block * sb)
32 {
33 cli();
34 while (sb->s_lock)
35 sleep_on(&(sb->s_wait));
36 sb->s_lock = 1;
37 sti();
38 }
如果其他任务已经锁定了,就等待它释放,然后自己锁定。
32 {
33 cli();
34 while (sb->s_lock)
35 sleep_on(&(sb->s_wait));
36 sb->s_lock = 1;
37 sti();
38 }
如果其他任务已经锁定了,就等待它释放,然后自己锁定。
40 static void free_super(struct super_block * sb)
41 {
42 cli();
43 sb->s_lock = 0;
44 wake_up(&(sb->s_wait));
45 sti();
46 }
这里其实是解锁操作,叫unlock更好一些
41 {
42 cli();
43 sb->s_lock = 0;
44 wake_up(&(sb->s_wait));
45 sti();
46 }
这里其实是解锁操作,叫unlock更好一些
48 static void wait_on_super(struct super_block * sb)
49 {
50 cli();
51 while (sb->s_lock)
52 sleep_on(&(sb->s_wait));
53 sti();
54 }
49 {
50 cli();
51 while (sb->s_lock)
52 sleep_on(&(sb->s_wait));
53 sti();
54 }
56 struct super_block * get_super(int dev)
57 {
58 struct super_block * s;
59
60 if (!dev)
61 return NULL;
62 s = 0+super_block;
63 while (s < NR_SUPER+super_block)
64 if (s->s_dev == dev) {
65 wait_on_super(s);
66 if (s->s_dev == dev)
67 return s;
68 s = 0+super_block; //重新从头开始搜索
69 } else
70 s++;
71 return NULL;
72 }
从这里可以看到super_block是保存在super_block数组中的。另外,当找到对应的super_block之后还要等待它被释放(65行),释放之后还要再进行一次判断(66行),因为中间super_block可能又会被其他任务锁定。
57 {
58 struct super_block * s;
59
60 if (!dev)
61 return NULL;
62 s = 0+super_block;
63 while (s < NR_SUPER+super_block)
64 if (s->s_dev == dev) {
65 wait_on_super(s);
66 if (s->s_dev == dev)
67 return s;
68 s = 0+super_block; //重新从头开始搜索
69 } else
70 s++;
71 return NULL;
72 }
从这里可以看到super_block是保存在super_block数组中的。另外,当找到对应的super_block之后还要等待它被释放(65行),释放之后还要再进行一次判断(66行),因为中间super_block可能又会被其他任务锁定。
74 void put_super(int dev) //释放超级块
75 {
76 struct super_block * sb;
77 struct m_inode * inode;
78 int i;
79
80 if (dev == ROOT_DEV) {
81 printk("root diskette changed: prepare for armageddon\n\r");
82 return;
75 {
76 struct super_block * sb;
77 struct m_inode * inode;
78 int i;
79
80 if (dev == ROOT_DEV) {
81 printk("root diskette changed: prepare for armageddon\n\r");
82 return;
这里的ROOT_DEV指的是根文件系统所在的分区
83 }
84 if (!(sb = get_super(dev)))
85 return;
86 if (sb->s_imount) {
87 printk("Mounted disk changed - tssk, tssk\n\r");
88 return;
89 }
90 lock_super(sb);
91 sb->s_dev = 0;
92 for(i=0;i<I_MAP_SLOTS;i++)
93 brelse(sb->s_imap[i]);
94 for(i=0;i<Z_MAP_SLOTS;i++)
95 brelse(sb->s_zmap[i]);
96 free_super(sb);
97 return;
98 }
83 }
84 if (!(sb = get_super(dev)))
85 return;
86 if (sb->s_imount) {
87 printk("Mounted disk changed - tssk, tssk\n\r");
88 return;
89 }
90 lock_super(sb);
91 sb->s_dev = 0;
92 for(i=0;i<I_MAP_SLOTS;i++)
93 brelse(sb->s_imap[i]);
94 for(i=0;i<Z_MAP_SLOTS;i++)
95 brelse(sb->s_zmap[i]);
96 free_super(sb);
97 return;
98 }
100 static struct super_block * read_super(int dev)
101 {
102 struct super_block * s;
103 struct buffer_head * bh;
104 int i,block;
106 if (!dev)
107 return NULL;
108 check_disk_change(dev);
109 if (s = get_super(dev))
110 return s;
101 {
102 struct super_block * s;
103 struct buffer_head * bh;
104 int i,block;
106 if (!dev)
107 return NULL;
108 check_disk_change(dev);
109 if (s = get_super(dev))
110 return s;
获取到直接返回
111 for (s = 0+super_block; ; s++) {
112 if (s >= NR_SUPER+super_block)
113 return NULL;
114 if (!s->s_dev)
115 break;
116 }
111 for (s = 0+super_block; ; s++) {
112 if (s >= NR_SUPER+super_block)
113 return NULL;
114 if (!s->s_dev)
115 break;
116 }
从super_block[]中找到一个s_dev为0的super_block。
117 s->s_dev = dev;
118 s->s_isup = NULL;
119 s->s_imount = NULL;
120 s->s_time = 0;
121 s->s_rd_only = 0;
122 s->s_dirt = 0;
初始化它的属性
123 lock_super(s); //锁定
124 if (!(bh = bread(dev,1))) { //读取该设备第一个块号,也就是超级块
125 s->s_dev=0; //读取失败
126 free_super(s);
127 return NULL;
128 }
到这里说明成功读取了超级块
129 *((struct d_super_block *) s) =
130 *((struct d_super_block *) bh->b_data);
用它来为s赋值
131 brelse(bh);
132 if (s->s_magic != SUPER_MAGIC) { //检查魔数
133 s->s_dev = 0;
134 free_super(s);
135 return NULL;
136 }
137 for (i=0;i<I_MAP_SLOTS;i++)
138 s->s_imap[i] = NULL;
139 for (i=0;i<Z_MAP_SLOTS;i++)
140 s->s_zmap[i] = NULL;
初始化imap和zmap
141 block=2;
142 for (i=0 ; i < s->s_imap_blocks ; i++)
143 if (s->s_imap[i]=bread(dev,block)) //读取相应的inode bitmap块,来为s_imap赋值
144 block++;
145 else
146 break;
147 for (i=0 ; i < s->s_zmap_blocks ; i++)
148 if (s->s_zmap[i]=bread(dev,block))
149 block++;
150 else
151 break;
读取相应的逻辑块bitmap来为s_zmap赋值
152 if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
正常情况下这里应该相等,否则就释放所有的buffer_head
153 for(i=0;i<I_MAP_SLOTS;i++)
154 brelse(s->s_imap[i]);
155 for(i=0;i<Z_MAP_SLOTS;i++)
156 brelse(s->s_zmap[i]);
157 s->s_dev=0;
158 free_super(s);
159 return NULL;
160 }
153 for(i=0;i<I_MAP_SLOTS;i++)
154 brelse(s->s_imap[i]);
155 for(i=0;i<Z_MAP_SLOTS;i++)
156 brelse(s->s_zmap[i]);
157 s->s_dev=0;
158 free_super(s);
159 return NULL;
160 }
161 s->s_imap[0]->b_data[0] |= 1;
162 s->s_zmap[0]->b_data[0] |= 1;
s_imap和s_zmap是buffer_head类型的,它的b_data对应着磁盘数据映射。这里把第0个位都置为1.因为第0个inode节点和逻辑块是不能被分配的。
163 free_super(s); //解锁超级块
164 return s;
165 }
从这里可以看出,super_block数组可以看做系统中super_block的缓存。
163 free_super(s); //解锁超级块
164 return s;
165 }
从这里可以看出,super_block数组可以看做系统中super_block的缓存。
167 int sys_umount(char * dev_name)
168 {
169 struct m_inode * inode;
170 struct super_block * sb;
171 int dev;
173 if (!(inode=namei(dev_name)))
174 return -ENOENT;
168 {
169 struct m_inode * inode;
170 struct super_block * sb;
171 int dev;
173 if (!(inode=namei(dev_name)))
174 return -ENOENT;
根据设备名找到对应的inode
175 dev = inode->i_zone[0];
取得设备号(设备文件在其i_zone[0]中存放设备号)
176 if (!S_ISBLK(inode->i_mode)) {
177 iput(inode); //如果不是块设备,放回inode即可
178 return -ENOTBLK;
179 }
180 iput(inode);
是块设备
181 if (dev==ROOT_DEV)
182 return -EBUSY;
如果是根设备,返回-EBUSY。
183 if (!(sb=get_super(dev)) || !(sb->s_imount))
184 return -ENOENT;
没有找到超级块或者该文件系统没有被安装过,返回
185 if (!sb->s_imount->i_mount)
186 printk("Mounted inode has i_mount=0\n");
如果超级块所指明的被安装到的inode节点的i_mount标志没有被置位,则打印信息。
187 for (inode=