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

来源:互联网 发布:心蓝软件 手机 编辑:程序博客网 时间:2024/04/30 02:52
#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;}elses++;}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);}}

原创粉丝点击