Mount the i node of the Root Device to the Root

Một phần của tài liệu The art of linux kernel design (Trang 172 - 175)

3.3.3 Process 1 Loads the Root File System into the Root Device

3.3.3.2 Mount the i node of the Root Device to the Root

Back to mount_root, it calls iget() to read the root i node from the Ramdisk. The signifi- cance of the root i node is as follows: any i node in the system can be located through the root i node, which means we can find any files in the system.

The code is as follows:

//the code path:fs/super.c:

static struct super_block * read_super(int dev) {

……

for (i = 0;i<I_MAP_SLOTS;i++) //initialize s_imap[8] and s_zmap[8]

s->s_imap[i] = NULL;

for (i = 0;i<Z_MAP_SLOTS;i++) s->s_zmap[i] = NULL;

block = 2; //the 1st block of Ramdisk

//is super block,

//the 2nd is I-node bitmap and //logical bitmap

for (i = 0 ; i < s->s_imap_blocks ; i++) //read all the logical block of //I-node bitmap to the buffer if (s->s_imap[i] = bread(dev,block)) //mount them to s_imap[8]

block++;

else break;

for (i = 0 ; i < s->s_zmap_blocks ; i++) //read all the logical block of logical bitmap to the buffer

if (s->s_zmap[i] = bread(dev,block)) //mount them to s_zmap[8]

block++;

else break;

if (block ! = 2+s->s_imap_blocks+s->s_zmap_blocks) { //if the number of blocks is wrong, for(i = 0;i<I_MAP_SLOTS;i++) //that means the system error

brelse(s->s_imap[i]); //free them for(i = 0;i<Z_MAP_SLOTS;i++)

brelse(s->s_zmap[i]);

s->s_dev = 0;

free_super(s);

return NULL;

}s->s_imap[0]->b_data[0] | = 1; //avoid return 0 and mix up with 0 I-node s->s_zmap[0]->b_data[0] | = 1;

free_super(s);

return s;

}

//the code path:fs/super.c:

void mount_root(void) {

……

if (!(p = read_super(ROOT_DEV))) panic(“Unable to mount root”);

if (!(mi = iget(ROOT_DEV,ROOT_INO)))

panic(“Unable to read root i-node”);

……

}

In iget(), the OS would apply for a free i node slot in inode_table[32] (inode_table[32]

is used by the OS to control the maximum number of concurrent opening files). At this stage, it should be the first i node; initialize the i node, including the device number of the i node, the node number of the i node. The location of the root i node in the kernel i node table is shown in Figure 3.45.

The code is as follows:

//the code path:fs/inode.c:

struct m_inode * iget(int dev,int nr) {

struct m_inode * inode, * empty;

if (!dev)

panic(“iget with dev ==0”);

empty = get_empty_inode(); //apply a location for I-node in //inode_table[32]

inode = inode_table;

while (inode < NR_INODE+inode_table) { //find the same inode if (inode->i_dev ! = dev || inode->i_num ! = nr) {

inode++;

continue;

ROM BIOS and VGA

\0 \0 \0 Kernel

Enable interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Kernel code area Kernel data area

super_block[8]

Loadsuper block

Unlock

RAM Drive Load i node bitmap

Load logical block bitmap

s_ninodes s_nzones s_imap_blocks s_zmap_blocks s_firstdatazone s_log_zone_size s_max_size s_magic s_imap[8]

s_zmap[8]

s_dev s_isup s_imount s_time s_wait s_lock s_rd_only s_dirt Process status

Process 0 Process 1

Ready Interruptible

Current process

Figure 3.44 Read the logical bitmap and the i node bitmap.

The function read_inode() first locks the i node in inode_table[32] so that the i node will not be used by another program until it is released. The function then calculates the logical block number of the i node through the super block of the i node and reads in the i node logical block, gets the information of the i node, and loads it to the i node location that has just been locked, as shown in Figure 3.46. Note the change in inode_table. Finally, it will free the buffer and unlock the i node.

The code is as follows:

}

wait_on_inode(inode); //wait for unlocking

if (inode->i_dev ! = dev || inode->i_num ! = nr) { //if it changes when waiting,

inode = inode_table; //go on finding continue;

}

inode->i_count++;

if (inode->i_mount) { int i;

for (i = 0 ; i<NR_SUPER ; i++) //if it is the mount point, if (super_block[i].s_imount = =inode) //find the super block

break;

if (i > = NR_SUPER) {

printk(“Mounted inode hasn’t got sb\n”);

if (empty)

iput(empty);

return inode;

}

iput(inode);

dev = super_block[i].s_dev; //get the device number in the //super block

nr = ROOT_INO; //ROOT_INO is 1,the node number //of root I

inode = inode_table;

continue;

} if (empty)

iput(empty);

return inode;

}

if (!empty)

return (NULL);

inode = empty;

inode->i_dev = dev; //initialize

inode->i_num = nr;

read_inode(inode); //read the root I-node from the

//Ramdisk return inode;

}

//the code path:fs/inode.c:

static void read_inode(struct m_inode * inode) {

……

lock_inode(inode); //lock the inode

if (!(sb = get_super(inode->i_dev))) //get the super block of the I-node

……

block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + (inode->i_num-1)/INODES_PER_BLOCK;

if (!(bh = bread(inode->i_dev,block))) //read the logical block of I-node panic(“unable to read i-node block”);

*(struct d_inode *)inode = //copy all ((struct d_inode *)bh->b_data)

[(inode->i_num-1)%INODES_PER_BLOCK];

brelse(bh); //free the buffer blocks

unlock_inode(inode); //unlock

Back to iGet, it returns the pointer inode to the function mount_root and assigns it to pointer mi.

The following is the process of loading the root file system:

Mount the Ramdisk root i node in inode_table[32] to the s_isup and s_imount in super_block[8]. Hence, the OS could find the files step by step through the relationship established here.

Một phần của tài liệu The art of linux kernel design (Trang 172 - 175)

Tải bản đầy đủ (PDF)

(524 trang)