📄 inode.c
字号:
#include <string.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
struct m_inode inode_table[NR_INODE]={{0,},};
static void read_inode(struct m_inode * inode);
static void write_inode(struct m_inode * inode);
static inline void wait_on_inode(struct m_inode * inode)
{
cli();
while (inode->i_lock)
sleep_on(&inode->i_wait); //在sched.c中定义
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); //在sched.c中定义
}
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);
}
}
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");
if (block<7) {
if (create && !inode->i_zone[block]) //如果是要创建,并且该直接块是null的
if (inode->i_zone[block]=new_block(inode->i_dev)) { //建立新块,将找到的块放入i_zone中
inode->i_ctime=CURRENT_TIME; //修改时间
inode->i_dirt=1; //要求写盘
}
return inode->i_zone[block];
}
block -= 7;
if (block<512) { //如果此块位于一级间接块
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;
if (!(bh = bread(inode->i_dev,inode->i_zone[7]))) //将一级间接块读入缓冲区
return 0;
i = ((unsigned short *) (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; //如果是二级间接块
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;
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;
}
int bmap(struct m_inode * inode,int block)
{
return _bmap(inode,block,0);
}
int create_block(struct m_inode * inode, int block)
{
return _bmap(inode,block,1);
}
void iput(struct m_inode * inode) //释放该节点及该节点使用的所有块(在内存map中)
{
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;
}
if (!inode->i_dev || inode->i_count>1) {
inode->i_count--;
return;
}
repeat:
if (!inode->i_nlinks) {
truncate(inode); //释放此节点的所有直接和间接块的map
free_inode(inode); //在s_imap表中清除该节点
return;
}
if (inode->i_dirt) {
write_inode(inode); /* we can sleep - so do again */
wait_on_inode(inode);
goto repeat;
}
inode->i_count--;
return;
}
static volatile int last_allocated_inode = 0;
struct m_inode * get_empty_inode(void)
{
struct m_inode * inode;
int inr;
while (1) {
inode = NULL;
inr = last_allocated_inode;
do { //这个循环是在inode_table中取得一个内存节点
if (!inode_table[inr].i_count) {
inode = inr + inode_table;
break;
}
inr++;
if (inr>=NR_INODE)
inr=0;
} while (inr != last_allocated_inode);
if (!inode) { //如果节点为空,那么出错
for (inr=0 ; inr<NR_INODE ; inr++)
printk("%04x: %6d\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);
while (inode->i_dirt) { //如果节点是脏的,那么写盘
write_inode(inode);
wait_on_inode(inode);
}
if (!inode->i_count)
break;
}
memset(inode,0,sizeof(*inode)); //将此节点初始化为0
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; //初始化管道为0
inode->i_pipe = 1; //标记该节点是一个管道
return 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_table; //inode指向inode_table[0]
while (inode < NR_INODE+inode_table) {
if (inode->i_dev != dev || inode->i_num != nr) { //寻找是否有dev和nr的内存节点
inode++;
continue;
}
wait_on_inode(inode); //等待释放此节点
if (inode->i_dev != dev || inode->i_num != nr) {
inode = inode_table;
continue;
}
inode->i_count++;
if (empty)
iput(empty);
return inode;
}
//以下代码是如果在当前的inode_table中没有现成的,所要执行的
if (!empty)
return (NULL);
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); //取得相应的i_dev所在的超级块
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK; //计算出块号
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block"); //读取节点所在的块进入buffer
*(struct d_inode *)inode =
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK]; //计算出该节点在这个块的位移
brelse(bh);
unlock_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); //get_super在fs.h中定义
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
((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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -