/*
_bmap实现i节点表示的文件,和存储文件数据的逻辑块之间的映射关系
inode为表示文件的i节点
block为文件数据块编号
create为标志位,指明当对应的逻辑块不存在时,是否需要新建逻辑块
*/
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) {
//block<7,只需要使用i_zone[0]~i_zone[6]直接存储逻辑块号即可
/*
当create标识为1,并且对应的逻辑块号不存在时,就需要新建逻辑块
*/
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;
//i节点的内容被修改
}
return
inode->i_zone[block]; //返回对应的逻辑块号
}
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_zone[7]表示的逻辑块中的数据看成是逻辑块号数组,数组的最大长度是512(BLOCK_SIZE/sizeof(unsigned short))
*/
i = ((
unsigned
short
*) (bh->b_data))[block];
/*
new_block申请新的磁盘块时,会把这个块的数据清零。所以,如果i为0,表示之前对应的逻辑块不存在。需要新建时,就申请逻辑
块用来存放文件数据,同时把这个申请的逻辑块的编号写入i_zone[7]表示的逻辑块中去,作为间接存储。
*/
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编号大于7+512,需要使用i_zone[8]来进行二次间接存储。
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_zone[8]对应的逻辑块,找到一个逻辑块,然后在这个逻辑块中找到真正的存储数据的逻辑块的编号。使用两层间接索引模式,在创建
新的逻辑块时,就需要两步才能实现。
首先,i_zone[8]表示的逻辑块中的数据,然后是下一层的逻辑块。在i_zone[8]表示的逻辑块中的逻辑块编号数组中,每个相邻元素之间相差
512。因此,在计算索引时,使用block/512,也就是block>>9。第二层的索引是在0~511之间,所以使用block&511。
也可以看成,把block的高8位表示在第一层的数组的索引,把block的低8位看成是在第二层的数组的索引
*/
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;
//设置i_zone[8]对应的逻辑块中的数据,也就是第一层的数组数据
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;
}