📄 ul_inode.cpp
字号:
// 该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 节点。
// 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);
}
//// 释放指定的i 节点。
// 复位对应i 节点位图比特位。
void free_inode (struct m_inode *inode)
{
struct super_block *sb;
struct buffer_head *bh;
// 如果i 节点指针=NULL,则退出。
if (!inode)
return;
// 如果i 节点上的设备号字段为0,说明该节点无用,则用0 清空对应i 节点所占内存区,并返回。
if (!inode->i_dev)
{
memset (inode, 0, sizeof (*inode));
return;
}
// 如果此i 节点还有其它程序引用,则不能释放,说明内核有问题,死机。
if (inode->i_count > 1)
{
printk ("trying to free inode with count=%d\n", inode->i_count);
panic ("free_inode");
}
// 如果文件目录项连接数不为0,则表示还有其它文件目录项在使用该节点,不应释放,而应该放回等。
if (inode->i_nlinks)
panic ("trying to free inode with links");
// 取i 节点所在设备的超级块,测试设备是否存在。
if (!(sb = get_super (inode->i_dev)))
panic ("trying to free inode on nonexistent device");
// 如果i 节点号=0 或大于该设备上i 节点总数,则出错(0 号i 节点保留没有使用)。
if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
panic ("trying to free inode 0 or nonexistant inode");
// 如果该i 节点对应的节点位图不存在,则出错。
if (!(bh = sb->s_imap[inode->i_num >> 13]))
panic ("nonexistent imap in superblock");
// 复位i 节点对应的节点位图中的比特位,如果该比特位已经等于0,则出错。
if (clear_bit (inode->i_num & 8191, bh->b_data))
printk ("free_inode: bit already cleared.\n\r");
// 置i 节点位图所在缓冲区已修改标志,并清空该i 节点结构所占内存区。
bh->b_dirt = 1;
memset (inode, 0, sizeof (*inode));
}
//// 为设备dev 建立一个新i 节点。返回该新i 节点的指针。
// 在内存i 节点表中获取一个空闲i 节点表项,并从i 节点位图中找一个空闲i 节点。
struct m_inode *new_inode (int dev)
{
struct m_inode *inode;
struct super_block *sb;
struct buffer_head *bh;
int i, j;
// 从内存i 节点表(inode_table)中获取一个空闲i 节点项(inode)。
if (!(inode = get_empty_inode ()))
return NULL;
// 读取指定设备的超级块结构。
if (!(sb = get_super (dev)))
panic ("new_inode with unknown device");
// 扫描i 节点位图,寻找首个0 比特位,寻找空闲节点,获取放置该i 节点的节点号。
j = 8192;
for (i = 0; i < 8; i++)
if (bh = sb->s_imap[i])
if ((j = find_first_zero (bh->b_data)) < 8192)
break;
// 如果全部扫描完还没找到,或者位图所在的缓冲块无效(bh=NULL)则 返回0,退出(没有空闲i 节点)。
if (!bh || j >= 8192 || j + i * 8192 > sb->s_ninodes)
{
iput (inode);
return NULL;
}
// 置位对应新i 节点的i 节点位图相应比特位,如果已经置位,则出错。
if (set_bit (j, bh->b_data))
panic ("new_inode: bit already set");
// 置i 节点位图所在缓冲区已修改标志。
bh->b_dirt = 1;
// 初始化该i 节点结构。
inode->i_count = 1; // 引用计数。
inode->i_nlinks = 1; // 文件目录项链接数。
inode->i_dev = dev; // i 节点所在的设备号。
inode->i_uid = 0; // i 节点所属用户id。
inode->i_gid = 0; // 组id。
inode->i_dirt = 1; // 已修改标志置位。
inode->i_num = j + i * 8192; // 对应设备中的i 节点号。
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; // 设置时间。
return inode; // 返回该i 节点指针。
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -