ul_super.cpp

来自「类似Linux操作系统0.11版文件系统的文件系统设计和Windows下的操作程」· C++ 代码 · 共 263 行

CPP
263
字号
/*
 * UNIX Like (UL)文件系统 spuer block 处理模块
 */
#include "stdafx.h"
#include "UL_FileSys.h"
#include "UL_Buffer.h"
#include "UL_Super.h"
#include "UL_Inode.h"
#include "UL_File.h"
#include "BlkDev.h"

int sync_dev (int dev);			// 对指定设备执行高速缓冲与设备上数据的同步操作(fs/buffer.c,59)


struct super_block super_block[NR_SUPER];	// 超级块结构数组(共8 项)

int ROOT_DEV = 0x301;

//// 锁定指定的超级块。
static void lock_super (struct super_block *sb)
{
}

//// 对指定超级块解锁。(如果使用ulock_super 这个名称则更妥帖)。
static void unlock_super (struct super_block *sb)
{
}

//// 取指定设备的超级块返回该超级块结构指针
struct super_block *get_super (int dev)
{
	struct super_block *s;

	if (!dev)
		return NULL;

	s = 0 + super_block;
	while (s < NR_SUPER + super_block)
	{
		if (s->s_dev == dev)
			return s;
		else
			s++;
	}
	return NULL;
}

//// 从设备上读取超级块到缓冲区中,如果该设备的超级块已经在高速缓冲中并且有效,则直接返回该超级块的指针
static struct super_block *read_super (int dev)
{
	struct super_block *s;
	struct buffer_head *bh;
	int i, block;

	if (!dev)
		return NULL;

	// 如果该设备的超级块已经在高速缓冲中,则直接返回该超级块的指针
	if (s = get_super (dev))
		return s;

	// 否则,首先在超级块数组中找出一个空项(也即其s_dev=0 的项)如果数组已经占满则返回空指针
	for (s = 0 + super_block;; s++)
	{
		if (s >= NR_SUPER + super_block)
			return NULL;
		if (!s->s_dev)
			break;
	}

	// 找到超级块空项后,就将该超级块用于指定设备,对该超级块的内存项进行部分初始化
	s->s_dev = dev;
	s->s_isup = NULL;
	s->s_imount = NULL;
	s->s_time = 0;
	s->s_rd_only = 0;
	s->s_dirt = 0;

	lock_super (s);
	// 从设备上读取超级块信息到bh 指向的缓冲区中如果读超级块操作失败,
	// 则释放上面选定的超级块数组中的项,并解锁该项,返回空指针退出
	if (!(bh = bread (dev, 1)))
	{
		s->s_dev = 0;
		unlock_super (s);
		return NULL;
	}

	// 将设备上读取的超级块信息复制到超级块数组相应项结构中并释放存放读取信息的高速缓冲块
	*((struct d_super_block *) s) = *((struct d_super_block *) bh->b_data);
	brelse (bh);

	// 如果读取的超级块的文件系统魔数字段内容不对
	// 只支持minix 文件系统版本1.0,其魔数是0x137f
	if (s->s_magic != SUPER_MAGIC)
	{
		s->s_dev = 0;
		unlock_super (s);
		return NULL;
	}

	// 下面开始读取设备上i 节点位图和逻辑块位图数据首先初始化内存超级块结构中位图空间
	for (i = 0; i < I_MAP_SLOTS; i++)
		s->s_imap[i] = NULL;
	for (i = 0; i < Z_MAP_SLOTS; i++)
		s->s_zmap[i] = NULL;

	// 然后从设备上读取i 节点位图和逻辑块位图信息,并存放在超级块对应字段中
	block = 2;
	for (i = 0; i < s->s_imap_blocks; i++)
	{
		if (s->s_imap[i] = bread (dev, block))
			block++;
		else
			break;
	}

	for (i = 0; i < s->s_zmap_blocks; i++)
	{
		if (s->s_zmap[i] = bread (dev, block))
			block++;
		else
			break;
	}

	// 如果读出的位图逻辑块数不等于位图应该占有的逻辑块数,说明文件系统位图信息有问题,超级块
	// 初始化失败因此只能释放前面申请的所有资源,返回空指针并退出
	if (block != 2 + s->s_imap_blocks + s->s_zmap_blocks)
	{
		for (i = 0; i < I_MAP_SLOTS; i++)
			brelse (s->s_imap[i]);
		for (i = 0; i < Z_MAP_SLOTS; i++)
			brelse (s->s_zmap[i]);
		s->s_dev = 0;
		unlock_super (s);
		return NULL;
	}

	// inode位图中的最低位设置为1
	// 逻辑块位图的最低位设置为1
	s->s_imap[0]->b_data[0] |= 0x80;
	s->s_zmap[0]->b_data[0] |= 0x80;

	unlock_super (s);
	return s;
}

//// 安装根文件系统 /////////////////////////////////////////////////////////////////////
int mount_root (void)
{
	int i, free;
	struct super_block *p;
	struct m_inode *mionde;

	if (32 != sizeof (struct d_inode))
	{
		panic ("mount_root: d_inode 大小错误\n");
		return -ENOENT;
	}

	// 初始化文件表数组共64 项
	for (i = 0; i < NR_FILE; i++)
		file_table[i].f_count = 0;

	// 初始化超级块数组(共8 项)
	for (p = &super_block[0]; p < &super_block[NR_SUPER]; p++)
	{
		p->s_dev = 0;
		p->s_lock = 0;
		p->s_wait = NULL;
	}

	// 如果读根设备上超级块失败,则显示信息,并死机
	if (!(p = read_super (ROOT_DEV)))
	{
		panic ("mount_root: 读取根设备超级块失败\n");
		return -ENOENT;
	}
	else
	{
		printk ("超级块: 节点数 = %d\n",p->s_ninodes);
		printk ("        逻辑块数 = %d\n",p->s_nzones);
		printk ("        i 位图占用的块数 = %d\n",p->s_imap_blocks);
		printk ("        块位图占用的块数 = %d\n",p->s_zmap_blocks);
		printk ("        第一个数据逻辑块 = %d\n",p->s_firstdatazone);
		printk ("        log(数据/逻辑) = %d\n",p->s_log_zone_size);
		printk ("        文件最大长度 = 0x%X\n",p->s_max_size);
		printk ("        文件系统魔数 = 0x%X\n",p->s_magic);
	}
	
	//从设备上读取文件系统的根i 节点(1),如果失败则显示出错信息,死机
	if (!(mionde = iget (ROOT_DEV, ROOT_INO)))
	{
		panic ("mount_root: 读取根inode节点失败\n");
		return -ENOENT;
	}

	// 该i 节点引用次数递增3 次因为下面266-268 行上也引用了该i 节点
	mionde->i_count += 3;

	// 置该超级块的被安装文件系统i 节点和被安装到的i 节点为该i 节点
	p->s_isup = p->s_imount = mionde;

	// 设置当前进程的当前工作目录和根目录i 节点
	current_pwd = mionde;
	current_root = mionde;

	// 统计该设备上空闲块数首先令i 等于超级块中表明的设备逻辑块总数
	free = 0;
	i = p->s_nzones;

	// 然后根据逻辑块位图中相应比特位的占用情况统计出空闲块数
	while (--i >= 0)
		if (!test_bit (i & 8191, p->s_zmap[i >> 13]->b_data))
			free++;

	// 显示设备上空闲逻辑块数/逻辑块总数
	printk ("%d/%d 空闲逻辑块\n\r", free, p->s_nzones);

	// 统计设备上空闲i 节点数首先令i 等于超级块中表明的设备上i 节点总数+1加1 是将0 节点
	// 也统计进去
	free = 0;
	i = p->s_ninodes + 1;
	while (--i >= 0)
		if (!test_bit (i & 8191, p->s_imap[i >> 13]->b_data))
			free++;

	// 显示设备上可用的空闲i 节点数/i 节点总数
	printk ("%d/%d 空闲inode节点\n\r", free, p->s_ninodes);

	return 0;
}

//// 系统同步 /////////////////////////////////////////////////////////////////////
int sys_sync(void)
{
	int i;
	struct buffer_head *bh;

	// 将i 节点写入高速缓冲
	sync_inodes ();

	// 扫描所有高速缓冲区,对于已被修改的缓冲块产生写盘请求,将缓冲中数据与设备中同步。
	bh = start_buffer;
	for (i = 0; i < NR_BUFFERS; i++, bh++)
	{
		if (bh->b_dirt)
			ll_rw_block (WRITE, bh);	// 产生写设备块请求。
	}
	return 0;
}
void get_zmap(char *pmap)
{
	struct super_block *p;
	p = get_super(ROOT_DEV);
	for (int i=0; i<8; i++) 
	{
		if (!p->s_zmap[i])
			return;
		memcpy(pmap, p->s_zmap[i]->b_data, 1024);
		pmap+=1024;
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?