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

xiaoxiao2021-02-28  121

#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); } }
转载请注明原文地址: https://www.6miu.com/read-47874.html

最新回复(0)