3.3.3 Process 1 Loads the Root File System into the Root Device
3.3.3.1 Copying the Super Block of the Root Device to the super_block[8]
In mount_root, the system initializes the super block management structure super_block[8]
and then sets the device lock flags and all processes waiting for unlock to 0. Whenever the system wants to exchange data in the form of a file with a device, it must load the super block of the device into the super_block[8]. The system is able to acquire some basic information of the device file system from super_block[8]; also, the super block of the root device works in the same way, as shown in Figure 3.41.
The code is as follows:
//the code path:fs/super.c:
void mount_root(void) {
int i,free;
struct super_block * p;
struct m_inode * mi;
if (32 ! = sizeof (struct d_inode)) panic(“bad i-node size”);
for(i = 0;i<NR_FILE;i++) //initialize file_table[32], prepare //for the following code
file_table[i].f_count = 0;
RAM Drive of Disk root device
super_block[8]
Current process inode table[32]
Root file system
s_imap s_zmap
i node of root
File system Reference Chapter 5
... ... ... ... ... ...
... ... ... ... ... ...
Figure 3.40 Overview of the file system.
rd_load() has “formatted” the Ramdisk and set it as a root device. Then, the system will call the function read_super(), reading the super block of the root device from the Ramdisk and copying it to super_block[8].
if (MAJOR(ROOT_DEV) == 2) {//2represents floppy disk, the root device is //Ramdisk, that is 1.
//conversely, load the root file system of floppy //disk.
printk(“Insert root floppy and press ENTER”);
wait_for_keypress();
}
//initialize super_block[8]
for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) { p->s_dev = 0;
p->s_lock = 0;
p->s_wait = NULL;
}
if (!(p = read_super(ROOT_DEV))) panic(“Unable to mount root”);
……
}
ROM BIOS and VGA
Kernel
Enable interruptEnable interrupupupupupupupt
0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF
Kernel code area Kernel data area
file_table[64] super_block[8]
Step 1:
initialize file_table[64] Step 2:
initialize super_block[8]
Process status
Process 0 Process 1
Ready Interruptible
Current process
Figure 3.41 Initialize kernel file table and super block.
The code is as follows:
In the function read_super(), it first checks whether the super block has been read into the super_block[8]. If the super_block is there, it will be used directly without loading again.
The code is as follows:
Because the root file system is not loaded, we need to apply a slot in super_block[8], as shown in Figure 3.42. Now, we find the first location of the super_block, initialize and lock it, and prepare for reading the super block of the root device.
The code is as follows:
//the code path:fs/super.c:
void mount_root(void) {
……
if (!(p = read_super(ROOT_DEV)))
panic(“Unable to mount root”);
……
}
//the code path:fs/super.c:
static struct super_block * read_super(int dev) {
struct super_block * s;
struct buffer_head * bh;
int i,block;
if (!dev)
return NULL;
check_disk_change(dev); //test whether change the disk if (s = get_super(dev))
return s;
……
}
//the code path:fs/super.c:
static struct super_block * read_super(int dev) {
……
for (s = 0+super_block ;; s++) {
if (s > = NR_SUPER+super_block) //NR_SUPER is 8 return NULL;
if (!s->s_dev) break;
}
s->s_dev = dev;
The whole process consists of the following steps: calling the function bread, loading the super block from the Ramdisk to the buffer, and copying it from the buffer to the first location of super_block[8]. We have introduced the function bread in Section 3.3.1.2; there is little difference here. As mentioned in Section 3.3.1.5, if we send an order to the hard disk, the system will call the function do_hd_request. Since we operate the Ramdisk now, the sys- tem calls the function do_rd_request. It is worth reminding that the Ramdisk is considered as a peripheral, but after all, it is the memory space, not the actual peripheral; thus, calling do_rd_request would not trigger any interrupt, such as hard disk interrupt (Figure 3.43).
After the super block was loaded into the buffer, the system would copy the super block data from the buffer to the first location of super_block[8]. After that, the root device is managed by super_block[8]; then, call the brelse function to free the buffer.
s->s_isup = NULL;
s->s_imount = NULL;
s->s_time = 0;
s->s_rd_only = 0;
s->s_dirt = 0;
lock_super(s); //lock the super
//block
……
}
Kernel
Enable interrupt ROM BIOS
and VGA
0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF
Kernel code area Kernel data area
super_block[8]
Find a free super block and lock it Process status
Process 0 Process 1
Ready Interruptible
Current process Figure 3.42 Loading root file system’s super block.
The code is as follows:
The system initializes the i node bitmap management structure s_imap and logical block bitmap management structure s_zmap in super_block[8]; then, load the i node bit- map and logical block bitmap into the buffer and mount them to s_imap[8] and s_zmap[8].
//the code path:fs/super.c:
static struct super_block * read_super(int dev) {
……
if (!(bh = bread(dev,1))) { //read the super block of root device to the buffer
s->s_dev = 0;
free_super(s); //free the super block return NULL;
}
*((struct d_super_block *) s) = //copy the super block from the buffer
*((struct d_super_block *) bh->b_data); //to the first location of super_block[8]
brelse(bh); //free the buffer
if (s->s_magic ! = SUPER_MAGIC) { //test the s_magic s->s_dev = 0;
free_super(s); //free the super block return NULL;
}
……
}
ROM BIOS and VGA
Kernel
Enable interrupt
\0\0 \0
0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF
Kernel code area Kernel data area
super_block[8]
Step 1:
read super block of root file system from RAM Drive to buffer block Step 2:
copy data of super block to kernel super block table Process status
Process 0 Process 1
Ready Interruptible
Current process
Figure 3.43 Copy the super block from the Ramdisk to the kernel super block table.
Because we will access them frequently, the system would not release them, and they will be kept in the buffer all the time.
As shown in Figure 3.44, the super block mounts the s_imap and s_zmap.
The code is as follows: