📄 ul_block.cpp
字号:
/*
* UNIX Like (UL)文件系统 block 处理模块
*/
#include "stdafx.h"
#include "UL_FileSys.h"
#include "UL_Super.h"
#include "UL_Buffer.h"
#include "UL_Block.h"
#include "UL_Inode.h"
//// 将指定地址(addr)处的一块内存清零
void clear_block(char* addr)
{
unsigned int *p = (unsigned int *)addr;
for (int i=0 ;i<1024/4; i++, p++)
*p = 0;
}
////向设备dev 申请一个逻辑块(盘块,区块)。返回逻辑块号(盘块号)。
// 置位指定逻辑块block 的逻辑块位图比特位。
int new_block (int dev)
{
struct buffer_head *bh;
struct super_block *sb;
int i, j;
if (!(sb = get_super (dev)))
panic ("new_block: 试图从一个不存在的设备上新建一个逻辑块\n");
// 寻找空闲逻辑块
j = 8192;
for (i = 0; i < 8; i++)
if (bh = sb->s_zmap[i])
if ((j = find_first_zero (bh->b_data)) < 8192)
break;
// 没有空闲逻辑块
if (i >= 8 || !bh || j >= 8192)
{
TRACE("没有空闲逻辑块\n");
return 0;
}
// 设置新逻辑块对应逻辑块位图中的比特位,若对应比特位已经置位,则出错,死机。
if (set_bit (j, bh->b_data))
panic ("new_block: 逻辑块位图已经置位\n");
bh->b_dirt = 1;
// 置对应缓冲区块的已修改标志。如果新逻辑块大于该设备上的总逻辑块数,则说明指定逻辑块在
// 对应设备上不存在。申请失败,返回0,退出。
j += i * 8192 + sb->s_firstdatazone - 1;
if (j >= sb->s_nzones)
return 0;
// 读取设备上的该新逻辑块数据(验证)。如果失败则死机。
if (!(bh = getblk (dev, j)))
panic ("new_block: 不能获得逻辑块\n")
;
// 新块的引用计数应为1。否则死机。
if (bh->b_count != 1)
panic ("new block: 逻辑块的引用计数不为1 (count != 1)\n");
// 将该新逻辑块清零,并置位更新标志和已修改标志。然后释放对应缓冲区,返回逻辑块号。
clear_block (bh->b_data);
bh->b_uptodate = 1;
bh->b_dirt = 1;
brelse (bh);
return j;
}
//// 释放设备dev 上数据区中的逻辑块block。
// 复位指定逻辑块block 的逻辑块位图比特位。
// 参数:dev 是设备号,block 是逻辑块号(盘块号)。
void free_block (int dev, int block)
{
struct super_block *sb;
struct buffer_head *bh;
// 取指定设备dev 的超级块,如果指定设备不存在,则出错死机。
if (!(sb = get_super (dev)))
panic ("new_block: 试图从一个不存在的设备上释放一个逻辑块\n");
if (block < sb->s_firstdatazone || block >= sb->s_nzones)
panic ("new_block: 试图释放一个不存在于inode.zone[]上的逻辑块\n");
// 从hash 表中寻找该块数据。若找到了则判断其有效性,并清已修改和更新标志,释放该数据块。
// 该段代码的主要用途是如果该逻辑块当前存在于高速缓冲中,就释放对应的缓冲块。
bh = get_hash_table (dev, block);
if (bh)
{
if (bh->b_count != 1)
{
printk ("free_block: 试图释放块 (%04x:%d), count=%d\n",
dev, block, bh->b_count);
return;
}
bh->b_dirt = 0; // 复位脏(已修改)标志位。
bh->b_uptodate = 0; // 复位更新标志。
brelse (bh);
}
// 计算block 在数据区开始算起的数据逻辑块号(从1 开始计数)。然后对逻辑块(区块)位图进行操作,
// 复位对应的比特位。若对应比特位原来即是0,则出错,死机。
block -= sb->s_firstdatazone - 1; // block = block - ( -1) ;
if (clear_bit (block & 8191, sb->s_zmap[block / 8192]->b_data))
{
printk ("free_block: block (%04x:%d) ", dev, block + sb->s_firstdatazone - 1);
panic ("free_block: 逻辑块位图已经复位\n");
}
// 置相应逻辑块位图所在缓冲区已修改标志。
sb->s_zmap[block / 8192]->b_dirt = 1;
}
//// 释放一次间接块
static void free_ind (int dev, int block)
{
struct buffer_head *bh;
unsigned short *p;
int i;
// 如果逻辑块号为0,则返回。
if (!block)
return;
// 读取一次间接块,并释放其上表明使用的所有逻辑块,然后释放该一次间接块的缓冲区。
if (bh = bread (dev, block))
{
p = (unsigned short *) bh->b_data; // 指向数据缓冲区。
for (i = 0; i < 512; i++, p++) // 每个逻辑块上可有512 个块号。
if (*p)
free_block (dev, *p); // 释放指定的逻辑块。
brelse (bh); // 释放缓冲区。
}
//其它字段
//i_zone[0]
//i_zone[1]
//i_zone[2]
//i_zone[3]
//i_zone[4]
//i_zone[5]
//i_zone[6]
//i 节点
//直接块号
//一次间接块
//二次间接块
//的一级块
//二次间接块
//的二级块
//一次间接块号
//二次间接块号
//i_zone[7]
//i_zone[8]
// 释放设备上的一次间接块。
free_block (dev, block);
}
//// 释放二次间接块。
static void free_dind (int dev, int block)
{
struct buffer_head *bh;
unsigned short *p;
int i;
// 如果逻辑块号为0,则返回。
if (!block)
return;
// 读取二次间接块的一级块,并释放其上表明使用的所有逻辑块,然后释放该一级块的缓冲区。
if (bh = bread (dev, block))
{
p = (unsigned short *) bh->b_data; // 指向数据缓冲区。
for (i = 0; i < 512; i++, p++) // 每个逻辑块上可连接512 个二级块。
if (*p)
free_ind (dev, *p); // 释放所有一次间接块。
brelse (bh); // 释放缓冲区。
}
// 最后释放设备上的二次间接块。
free_block (dev, block);
}
//// 将节点对应的文件长度截为0,并释放占用的设备空间。
void truncate (struct m_inode *inode)
{
int i;
// 如果不是常规文件或者是目录文件,则返回。
if (!(S_ISREG (inode->i_mode) || S_ISDIR (inode->i_mode)))
return;
// 释放i 节点的7 个直接逻辑块,并将这7 个逻辑块项全置零。
for (i = 0; i < 7; i++)
if (inode->i_zone[i])
{ // 如果块号不为0,则释放之。
free_block (inode->i_dev, inode->i_zone[i]);
inode->i_zone[i] = 0;
}
free_ind (inode->i_dev, inode->i_zone[7]); // 释放一次间接块。
free_dind (inode->i_dev, inode->i_zone[8]); // 释放二次间接块。
inode->i_zone[7] = inode->i_zone[8] = 0; // 逻辑块项7、8 置零。
inode->i_size = 0; // 文件大小置零。
inode->i_dirt = 1; // 置节点已修改标志。
inode->i_mtime = inode->i_ctime = CURRENT_TIME; // 重置文件和节点修改时间为当前时间。
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -