struct m_inode inode_table[NR_INODE]={{0,},};
static void read_inode(struct m_inode * inode);
static void write_inode(struct m_inode * inode);
/*参考sleep_on函数,另一篇文中有说*/
static inline void wait_on_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait);
sti();
}
static inline void lock_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait);
inode->i_lock=1;
sti();
}
static inline void unlock_inode(struct m_inode * inode)
{
inode->i_lock=0;
wake_up(&inode->i_wait);
}
/*把所有的inode写入到磁盘中。读取的inode记录在全局数组inode_table中*/
void sync_inodes(void)
{
int i;
struct m_inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
wait_on_inode(inode);
if (inode->i_dirt && !inode->i_pipe)
write_inode(inode);
}
}
/*
*直接映射时,i_zone[0-6]分别记录一个块,也就是记录7个块
*一级间接映射:i_zone[7]指向一个块,块中的所有数据都用来记录下一级的块号。可记录512块
*二级间接映射i_zone[8]指向一个块a,块a用来记录512个块,这512个块又分别记录512个块号
*/
/*create=0时获取数据块再设备上的逻辑块号,create=1时创建数据块对应的逻辑块*/
/*0-6直接块 7一级间接映射块,8二级间接映射块*/
static int _bmap(struct m_inode * inode,int block,int create)
{
struct buffer_head * bh;
int i;
if (block<0)
panic("_bmap: block<0");
if (block >= 7+512+512*512)
panic("_bmap: block>big");
/*当block小于7时,且逻辑块映射成员i_zone[block]为空,就创建一个新块并赋值给i_zone[block];并返回逻辑块号*/
if (block<7) {
if (create && !inode->i_zone[block])
if (inode->i_zone[block]=new_block(inode->i_dev)) {
inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode->i_zone[block];
}
/*当块大于7时,就需要使用间接块映射逻辑块*/
block -= 7;
if (block<512) {
/*先为i_zone[7]创建一个新块,设置为脏,并更新时间*/
if (create && !inode->i_zone[7])
if (inode->i_zone[7]=new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[7])
return 0;
/*读取为i_zone[7]创建的块*/
if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
return 0;
/*把数据块对应的逻辑块号赋给i*/
i = ((unsigned short *) (bh->b_data))[block];
/*如果create=1,且i为0,则为i创建一个新块,并记录块号。并把块号记录到i和(bh->b_data))[block](记录的是映射的二级逻辑块号)中*/
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
/*当block大于512时,就需要创建二级逻辑映射了*/
block -= 512;
/*先为i_zone[8]分配一个块*/
if (create && !inode->i_zone[8])
if (inode->i_zone[8]=new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[8])
return 0;
/*读取i_zone[8]记录的块*/
if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
return 0;
i = ((unsigned short *)bh->b_data)[block>>9];
/*再为下一块分配一个块,并记录块号*/
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block>>9]=i;
bh->b_dirt=1;
}
brelse(bh);
if (!i)
return 0;
/*再读取第二级的块*/
if (!(bh=bread(inode->i_dev,i)))
return 0;
i = ((unsigned short *)bh->b_data)[block&511];
/*为第二级块分配块,并记录,这就是真正的额逻辑块了*/
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block&511]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
/*根据i节点信息,获取数据块再设备上的逻辑块号*/
int bmap(struct m_inode * inode,int block)
{
return _bmap(inode,block,0);
}
/*创建一个block*/
int create_block(struct m_inode * inode, int block)
{
return _bmap(inode,block,1);
}
/*释放一个节点*/
void iput(struct m_inode * inode)
{
if (!inode)
return;
wait_on_inode(inode);
/*如果节点就是空的,出错*/
if (!inode->i_count)
panic("iput: trying to free free inode");
/*如果节点是管道类型的,则给结构体成员赋值如下(具体的还没有分析到管道那块,回头分析了补上)*/
if (inode->i_pipe) {
wake_up(&inode->i_wait);
if (--inode->i_count)
return;
free_page(inode->i_size);
inode->i_count=0;
inode->i_dirt=0;
inode->i_pipe=0;
return;
}
/*如果是块设备文件的i节点,此时逻辑块字段0为设备号,刷新设备*/
if(S_ISBLK(inode->i_mode))
{
sync_dev(inode->i_zone[0]);
wait_on_inode(inode);
}
/*如果inode设备号为0,或引用数大于1,则引用计数减1,然后返回*/
if (!inode->i_dev || inode->i_count>1) {
inode->i_count--;
return;
}
repeat:
/*如果节点链接数为0,则截断节点,并释放节点到位图中*/
if (!inode->i_nlinks) {
truncate(inode);
free_inode(inode);
return;
}
/*如果节点已经修改,则写节点内容到缓冲区中*/
if (inode->i_dirt) {
write_inode(inode); /* we can sleep - so do again */
wait_on_inode(inode);
goto repeat;
}
/*节点引用数减1,然后返回*/
inode->i_count--;
return;
}
static volatile int last_allocated_inode = 0;
/*得到一个空的inode*/
struct m_inode * get_empty_inode(void)
{
struct m_inode * inode;
int inr;
/*循环查找*/
while (1) {
inode = NULL;
inr = last_allocated_inode;
do {
/*判断那个节点的使用数为0,就记录下对应的那个inode*/
if (!inode_table[inr].i_count) {
inode = inr + inode_table;
break;
}
inr++;
if (inr>=NR_INODE)
inr=0;
} while (inr != last_allocated_inode);
/*如果没有找到空的inode就报错*/
if (!inode) {
for (inr=0 ; inr<NR_INODE ; inr++)
printk("x: m\t",inode_table[inr].i_dev,
inode_table[inr].i_num);
panic("No free inodes in mem");
}
last_allocated_inode = inr;
wait_on_inode(inode);
/*如果inode已修改,则把inode写入到缓冲区中*/
while (inode->i_dirt) {
write_inode(inode);
wait_on_inode(inode);
}
/*如果最终找到一个空inode,就退出循环*/
if (!inode->i_count)
break;
}
/*清空inode,记录inode引用数为1*/
memset(inode,0,sizeof(*inode));
inode->i_count = 1;
return inode;
}
/*得到一个管道节点*/
struct m_inode * get_pipe_inode(void)
{
struct m_inode * inode;
if (!(inode = get_empty_inode()))
return NULL;
if (!(inode->i_size=get_free_page())) {
inode->i_count = 0;
return NULL;
}
inode->i_count = 2; /* sum of readers/writers */
PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
inode->i_pipe = 1;
return inode;
}
/*读取指定设备的指定的inode,参数:dev设备号 nr是inode号*/
struct m_inode * iget(int dev,int nr)
{
struct m_inode * inode, * empty;
if (!dev)
panic("iget with dev==0");
empty = get_empty_inode(); //得到一个空inode
inode = inode_table; //再inode_table中查找指定设备的指定的inode
while (inode < NR_INODE+inode_table) {
if (inode->i_dev != dev || inode->i_num != nr) {
inode++;
continue;
}
wait_on_inode(inode);
/*再检查一次,是保证再n睡眠期间没有其他进程进行修改*/
if (inode->i_dev != dev || inode->i_num != nr) {
inode = inode_table;
continue;
}
inode->i_count++; //inode的引用数加1
if (empty) //如果empty分配成功,则释放掉
iput(empty);
return inode;
}
if (!empty) //如果empty没有分配成功,则返回null
return (NULL);
/*让inode指向empty空的inode,并设置其设备号和inode号,然后根据设备号和inode号从磁盘读取节点的内容到inode中*/
inode=empty;
inode->i_dev = dev;
inode->i_num = nr;
read_inode(inode);
return inode;
}
/*读取指定节点*/
static void read_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
/*读取超级块*/
sb=get_super(inode->i_dev);
/*得到block号*/
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
/*如果读取对应设备的inode的block 到缓冲区中失败,则报错*/
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
/*把读取到缓冲区的那个inode的对应的内容写入到要写入的那个inode中*/
*(struct d_inode *)inode =
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK];
brelse(bh);
unlock_inode(inode);
}
/*把inode中的信息写入到磁盘中*/
static void write_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
/*读取超级块内容*/
sb=get_super(inode->i_dev);
/*计算要写的inode对应的block号,block=引导块+超级块+节点位图所占块+block位图所占块+inode块号*/
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
/*把inode的读取到缓冲区中*/
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
/*把inode的信息写入到bh->b_data中,并设置缓冲区脏标志随后会写入到磁盘中。inode设置为空*/
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK] =
*(struct d_inode *)inode;
bh->b_dirt=1;
inode->i_dirt=0;
brelse(bh);
unlock_inode(inode);
}