📄 inode.c
字号:
{ inode->i_count--; return; }// 如果是块设备文件的i 节点,此时逻辑块字段0 中是设备号,则刷新该设备。并等待i 节点解锁。 if (S_ISBLK (inode->i_mode)) { sync_dev (inode->i_zone[0]); wait_on_inode (inode); }repeat:// 如果i 节点的引用计数大于1,则递减1。 if (inode->i_count > 1) { inode->i_count--; return; }// 如果i 节点的链接数为0,则释放该i 节点的所有逻辑块,并释放该i 节点。 if (!inode->i_nlinks) { truncate (inode); free_inode (inode); return; }// 如果该i 节点已作过修改,则更新该i 节点,并等待该i 节点解锁。 if (inode->i_dirt) { write_inode (inode); /* we can sleep - so do again */ wait_on_inode (inode); goto repeat; }// i 节点引用计数递减1。 inode->i_count--; return;}//// 从i 节点表(inode_table)中获取一个空闲i 节点项。// 寻找引用计数count 为0 的i 节点,并将其写盘后清零,返回其指针。struct m_inode *get_empty_inode (void){ struct m_inode *inode; static struct m_inode *last_inode = inode_table; // last_inode 指向i 节点表第一项。 int i; do {// 扫描i 节点表。 inode = NULL; for (i = NR_INODE; i; i--) {// 如果last_inode 已经指向i 节点表的最后1 项之后,则让其重新指向i 节点表开始处。 if (++last_inode >= inode_table + NR_INODE) last_inode = inode_table;// 如果last_inode 所指向的i 节点的计数值为0,则说明可能找到空闲i 节点项。让inode 指向// 该i 节点。如果该i 节点的已修改标志和锁定标志均为0,则我们可以使用该i 节点,于是退出循环。 if (!last_inode->i_count) { inode = last_inode; if (!inode->i_dirt && !inode->i_lock) break; } }// 如果没有找到空闲i 节点(inode=NULL),则将整个i 节点表打印出来供调试使用,并死机。 if (!inode) { for (i = 0; i < NR_INODE; i++) printk ("%04x: %6d\t", inode_table[i].i_dev, inode_table[i].i_num); panic ("No free inodes in mem"); }// 等待该i 节点解锁(如果又被上锁的话)。 wait_on_inode (inode);// 如果该i 节点已修改标志被置位的话,则将该i 节点刷新,并等待该i 节点解锁。 while (inode->i_dirt) { write_inode (inode); wait_on_inode (inode); } } while (inode->i_count); // 如果i 节点又被其它占用的话,则重新寻找空闲i 节点。// 已找到空闲i 节点项。则将该i 节点项内容清零,并置引用标志为1,返回该i 节点指针。 memset (inode, 0, sizeof (*inode)); inode->i_count = 1; return inode;}//// 获取管道节点。返回为i 节点指针(如果是NULL 则失败)。// 首先扫描i 节点表,寻找一个空闲i 节点项,然后取得一页空闲内存供管道使用。// 然后将得到的i 节点的引用计数置为2(读者和写者),初始化管道头和尾,置i 节点的管道类型表示。struct m_inode *get_pipe_inode (void){ struct m_inode *inode; if (!(inode = get_empty_inode ())) // 如果找不到空闲i 节点则返回NULL。 return NULL; if (!(inode->i_size = get_free_page ())) { // 节点的i_size 字段指向缓冲区。 inode->i_count = 0; // 如果已没有空闲内存,则 return NULL; // 释放该i 节点,并返回NULL。 } inode->i_count = 2; /* sum of readers/writers *//* 读/写两者总计 */ PIPE_HEAD (*inode) = PIPE_TAIL (*inode) = 0; // 复位管道头尾指针。 inode->i_pipe = 1; // 置节点为管道使用的标志。 return inode; // 返回i 节点指针。}//// 从设备上读取指定节点号的i 节点。// nr - i 节点号。struct m_inode *iget (int dev, int nr){ struct m_inode *inode, *empty; if (!dev) panic ("iget with dev==0");// 从i 节点表中取一个空闲i 节点。 empty = get_empty_inode ();// 扫描i 节点表。寻找指定节点号的i 节点。并递增该节点的引用次数。 inode = inode_table; while (inode < NR_INODE + inode_table) {// 如果当前扫描的i 节点的设备号不等于指定的设备号或者节点号不等于指定的节点号,则继续扫描。 if (inode->i_dev != dev || inode->i_num != nr) { inode++; continue; }// 找到指定设备号和节点号的i 节点,等待该节点解锁(如果已上锁的话)。 wait_on_inode (inode);// 在等待该节点解锁的阶段,节点表可能会发生变化,所以再次判断,如果发生了变化,则再次重新// 扫描整个i 节点表。 if (inode->i_dev != dev || inode->i_num != nr) { inode = inode_table; continue; }// 将该i 节点引用计数增1。 inode->i_count++; if (inode->i_mount) { int i;// 如果该i 节点是其它文件系统的安装点,则在超级块表中搜寻安装在此i 节点的超级块。如果没有// 找到,则显示出错信息,并释放函数开始获取的空闲节点,返回该i 节点指针。 for (i = 0; i < NR_SUPER; i++) if (super_block[i].s_imount == inode) break; if (i >= NR_SUPER) { printk ("Mounted inode hasn't got sb\n"); if (empty) iput (empty); return inode; }// 将该i 节点写盘。从安装在此i 节点文件系统的超级块上取设备号,并令i 节点号为1。然后重新// 扫描整个i 节点表,取该被安装文件系统的根节点。 iput (inode); dev = super_block[i].s_dev; nr = ROOT_INO; inode = inode_table; continue; }// 已经找到相应的i 节点,因此放弃临时申请的空闲节点,返回该找到的i 节点。 if (empty) iput (empty); return inode; }// 如果在i 节点表中没有找到指定的i 节点,则利用前面申请的空闲i 节点在i 节点表中建立该节点。// 并从相应设备上读取该i 节点信息。返回该i 节点。 if (!empty) return (NULL); inode = empty; inode->i_dev = dev; inode->i_num = nr; read_inode (inode); return inode;}//// 从设备上读取指定i 节点的信息到内存中(缓冲区中)。static voidread_inode (struct m_inode *inode){ struct super_block *sb; struct buffer_head *bh; int block;// 首先锁定该i 节点,取该节点所在设备的超级块。 lock_inode (inode); if (!(sb = get_super (inode->i_dev))) panic ("trying to read inode without dev");// 该i 节点所在的逻辑块号 = (启动块+超级块) + i 节点位图占用的块数 + 逻辑块位图占用的块数 +// (i 节点号-1)/每块含有的i 节点数。 block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + (inode->i_num - 1) / INODES_PER_BLOCK;// 从设备上读取该i 节点所在的逻辑块,并将该inode 指针指向对应i 节点信息。 if (!(bh = bread (inode->i_dev, block))) panic ("unable to read i-node block"); *(struct d_inode *) inode = ((struct d_inode *) bh->b_data)[(inode->i_num - 1) % INODES_PER_BLOCK];// 最后释放读入的缓冲区,并解锁该i 节点。 brelse (bh); unlock_inode (inode);}//// 将指定i 节点信息写入设备(写入缓冲区相应的缓冲块中,待缓冲区刷新时会写入盘中)。static voidwrite_inode (struct m_inode *inode){ struct super_block *sb; struct buffer_head *bh; int block;// 首先锁定该i 节点,如果该i 节点没有被修改过或者该i 节点的设备号等于零,则解锁该i 节点,// 并退出。 lock_inode (inode); if (!inode->i_dirt || !inode->i_dev) { unlock_inode (inode); return; }// 获取该i 节点的超级块。 if (!(sb = get_super (inode->i_dev))) panic ("trying to write inode without device");// 该i 节点所在的逻辑块号 = (启动块+超级块) + i 节点位图占用的块数 + 逻辑块位图占用的块数 +// (i 节点号-1)/每块含有的i 节点数。 block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + (inode->i_num - 1) / INODES_PER_BLOCK;// 从设备上读取该i 节点所在的逻辑块。 if (!(bh = bread (inode->i_dev, block))) panic ("unable to read i-node block");// 将该i 节点信息复制到逻辑块对应该i 节点的项中。 ((struct d_inode *) bh->b_data) [(inode->i_num - 1) % INODES_PER_BLOCK] = *(struct d_inode *) inode;// 置缓冲区已修改标志,而i 节点修改标志置零。然后释放该含有i 节点的缓冲区,并解锁该i 节点。 bh->b_dirt = 1; inode->i_dirt = 0; brelse (bh); unlock_inode (inode);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -