📄 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 void read_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 void write_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 + -