⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ul_block.cpp

📁 类似Linux操作系统0.11版文件系统的文件系统设计和Windows下的操作程序
💻 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 + -