linux-011文件系统超级块的操作函数(挂载卸载系统)解析

#define set_bit(bitnr,addr)({\
register int _res __asm__("ax");\
__asm__("bt %2 %3;setb %%al":"=a"(__res):"a"(0),\
	"r"(bitnr),"m"(*(addr)));\
	__res; \
})

/*超级块表*/
struct super_block super_block[NR_SUPER];

int ROOT_DEV=0;
/*给超级块加锁*/
static void lock_super(struct super_block *sb)
{
		cli();
		while(sb->s_lock)
				sleep_on(%(sb->s_wait));
		sb->s_lock = 1;
		sti();
}
/*超级块解锁*/
static void free_super(struct super_block *sb)
{
	cli();
	sb->s_lock=0;
	wake_up(&(sb->s_wait));
	sti();
}
/*使等待的进程睡眠*/
static void wait_on_super(struct super_block *sb)
{
	cli();
	while(sb->s_lock)
		sleep_on(&(sb->s_wait));
	sti();
}
/*得到指定设备的超级块*/
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)
		{
			wait_on_super(s);
			if(s->s_dev == dev)
					return s;
			s = 0+super_block;
		}
		else
			s++;
	}
		return NULL;
}

/*释放超级块*/
void put_super(int dev)
{
	struct super_block*sb;
	struct m_inode *inode;
	int i;
	/*如果要释放的超级块是根设备的,则返回*/
	if(dev == ROOT_DEV)
	{
		printk("root diskette changed:prepare for armageddon");
		return;
	}
	/*如果超级块表中没有这个设备的超级块,饭会*/
	if(!(sb = get_super(dev)))
			return;
	/*如果超级块上装有其他文件系统,显示警告退出*/
	if(sb->s_imount)
	{
		printk("Mounted disk changed --tssk,tssk");
		return;
	}
	lock_super(sb);
	/*指定超级块设备为0,即要进行释放*/
	sb->s_dev=0;
	/*释放i节点位图,和block位图*/
	for(i=0;i<I_MAP_SLOTS;i++)
			brelse(sb->sb->s_imap[i]);
	for(i=0;i<Z_MAP_SLOTS;i++)
			brelse(sb->s_zmap[i]);
	free_super(sb);
	return;
}


static struct super_block * read_super(int dev)
{
	struct super_block *s;
	struct buffer_head *bh;
	int i,block;
	if(!dev)
		return null;
	check_disk_change(dev);
/*如果在超级块表中找到了指定设备的超级块,则返回这个超级块*/
	if(s = get_super(dev))
		return s;
	/*如果超级块表中所有项都为空*/
	for(s = 0+super_block;;s++)
	{
			if(s >= NR_SUPER+super_block)
					return NULL;
			if(!s->s_dev)
					break;
	}
	/*则给超级块s进行赋值,指定设备号*/
	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;
/*给s加锁*/
	lock_super(s);
/*读取指定设备的第一个块到缓冲区中*/
	if(!(bh = bread(dev,1)))
	{
		s->s_dev = 0;
		free_super(s);
		return NULL;
	}
	/*把读取到的数据转换为超级块*/
	*((struct d_super_block*)s)=*((struct d_super_block*)bh->b_data);
	 brelse(bh);

	 if(s->s_magic != SUPER_MAGIC)
	 {
	 	s->s_dev = 0;
	 	free_super(s);
	 	return NULL;
	 }
	 /*设置inode位图为null,block位图为空*/
	 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;
	 block =2;
	 /*读取设备上的i节点位图信息到缓存以及block位图到缓存*/
	 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;
	 	free_super(s);
	 	return NULL;
	 }
	 /*设置0号i节点和block,放置被系统分配出去*/
	 s->s_imap[0]->b_data[0] |= 1;
	 s->s_zmap[0]->b_data[0] |= 1;

	 free_super(s);
	 return s;
}

int sys_umount(char *dev_name)
{
	struct m_inode *inode;
	struct super_block *sb;
	int dev;
/*z根据dev_name找到i节点*/
	if(!(inode=namei(dev_name)))
		return -ENOENT;
	/*0号zone记录设备号*/
	dev = inode->i_zone[0];
/*如果不是块设备则释放节点,返回错误*/
	if(!S_ISBLK(inode->imode))
	{
		iput(inode);
		return -ENOTBLK;
	}
	/*释放节点*/
	iput(inode);
	/*如果设备为根设备,返回错误*/
	if(dev == ROOT_DEV)
		return -EBUSY;
	/*如果读取不到超级块,也没有安装文件系统,返回错误信息*/
	if(!(sb = get_super(dev)) || !(sb->s_imount))
		return -ENOENT;
	/*如果超级块指明的安装点的i节点没有安装信息,返回错误*/
	if(!sb->s_imount->i_mount)
		printk("mounted inode has i_mount=0");
	/*查看i节点表,看是否有进程在适用这个节点,有就返回错误*/
	for(inode=inde_table+0;inode<inode_table+NR_INODE;inode++)
		{
			if(inode->i_dev == dev && inode->i_count)
					return -EBUSY;
		}
/*复位被安装到的i节点的安装标志,释放该i节点*/
	sb->s_imount->i_mount = 0;
	iput(sb->s_imount);
/*置超级块中被安装i节点字段为空,并释放设备文件系统的根i节点,置超级块中被安装系统根i节点指针为空*/
	sb->s_imount =NULL;
	iput(sb->s_isup);
	sb->s_isup = NULL;
/*释放给设备的超级块以及位图占用的缓冲块,并对给设备进行高速缓冲到设备上的同步操作*/
	put_super(dev);
	sync_dev(dev);
	return 0;
}


int sys_mount(char*dev_name,char*dir_name,int rw_flag)
{
	struct m_inode *dev_i,*dir_i;
	struct super_block *sb;
	int dev;
/*根据设备名dev_name读取对应的节点*/
	if(!(dev_i!= namei(dev_name)))
			return -ENOENT;
/*取设备号*/
	dev = dev_i->i_zone[0];
/*判断是否是块设备*/
	if(!S_ISBLK(dev_i->i_mode))
	{
		iput(dev_i);
		return -EPERM;
	}
	iput(dev_i);
	/*获取要挂载的目录的节点*/
	if(!(dir_i=namei(dir_name)))
		return -ENOENT;
	/*如果目标目录引用数不为1,而且i节点号为ROOT_INO则释放节点,返回错误*/
	if(dir_i->i_count != 1 || dir_i->i_num == ROOT_INO)
	{
		iput(dir_i);
		return -EBUSY;
	}
	/*判断要挂载目录是否是目录*/
	if(!S_ISDIR(dir_i->i_mode))
	{
		iput(dir_i);
		return -EPERM;
	}
	/*读取设备的超级块*/
	if(!(sb = read_super(dev)))
	{
		iput(dir_i);
		return -EBUSY;
	}
	/*如果dir_i已经挂载了文件系统,则释放dir_i,并返回错误*/
	if(dir_i->i_mount)
	{
		iput(dir_i);
		return -EPERM;
	}
	/*如果都正确,则设置设备的超级块安装目录为dir_i,并设置dir_i的安装文件系统标志,以及被修改标志*/
	sb->s_imount = dir_i;
	dir_i->i_mount = 1;
	dir_i->i_dirt = 1;
	return 0;
}

void mount_root(void)
{
	int i,free;
	struct super_block *p;
	struct m_inode *mi;
	/*判断i节点大小*/
	if(32!=sizeof(struct d_inode))
		panic("bad i_node size");
	/*初始化文件描述符表*/
	for(i=0;i<NR_FILE;i++)
		file_table[i].f_count = 0;
	/*如果主设备号为2,打印下面信息*/
	if(MAJOR(ROOT_DEV)==2)
	{
		printk("insert root flopy and press enter");
		wait_for_keypress();
	}
	/*初始化超级块表*/
	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("unable to mount root");
	/*得到根设备的inode信息*/
	if(!(mi=iget(ROOT_DEV,ROOT_INO)))
		panic("unable to read root inode");
	mi->i_count += 3;
/*设置根设备安装点和安装目录都是mi*/
	p->s_isup = p->s_imount = mi;
	/*设置当前目录根目录都是mi*/
	current->pwd=mi;
	current->root=mi;
	free=0;
	i = p->s_nzones;
	/*计算block空余数量*/
	while(--i>0)
	{
		if(!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
			free++;
		printk("%d/%d free blocks",free,p->s_nzones);
	}
	/*计算inode空闲数量*/
	free = 0;
	i= p->ninodes +1;
	while(--i>=0)
	{
		if(!set_bit(i&8191,p->imap[i>>13]->b_data))
			free++;
		printk("%d/%d free inodes",free,p->s_ninodes);
	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值