#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);
}
}
linux-011文件系统超级块的操作函数(挂载卸载系统)解析
最新推荐文章于 2022-10-12 10:48:51 发布