linux-011中位图操作函数(申请释放节点,申请释放block)解析

来源:互联网 发布:淘宝补单技巧 编辑:程序博客网 时间:2024/05/21 14:47
/*把addr开始一块block地址清0*/#define clear_block(addr) \__asm__("cld\n\t" \"rep\n\t" \"stosl" \::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")/*把addr中偏移为nr的位置1*/#define set_bit(nr,addr) ({\register int res __asm__("ax"); \__asm__("btsl %2,%3\n\tsetb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \res;})/*把addr中偏移位nr的位清0*/#define clear_bit(nr,addr) ({\register int res __asm__("ax"); \__asm__("btrl %2,%3\n\tsetnb %%al":"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \res;})/*把addr中第一个为0的位偏移返回*/#define find_first_zero(addr) ({ \int __res; \__asm__("cld\n" \"1:\tlodsl\n\t" \"notl %%eax\n\t" \"bsfl %%eax,%%edx\n\t" \"je 2f\n\t" \"addl %%edx,%%ecx\n\t" \"jmp 3f\n" \"2:\taddl $32,%%ecx\n\t" \"cmpl $8192,%%ecx\n\t" \"jl 1b\n" \"3:" \:"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \__res;})/*释放设备dev的指定块block*/void free_block(int dev, int block){struct super_block * sb;struct buffer_head * bh;/*获取超级块*/if (!(sb = get_super(dev)))panic("trying to free block on nonexistent device");/*如果block不再第一个块号和最大块号之间,出错*/if (block < sb->s_firstdatazone || block >= sb->s_nzones)panic("trying to free block not in datazone");/*从hash表中查找block*/bh = get_hash_table(dev,block);/*如果hash表中存在,且引用数不等于1,出错。如果等于1则置缓冲区脏标志为0,数据不为最新并释放缓冲区*/if (bh) {if (bh->b_count != 1) {printk("trying to free block (%04x:%d), count=%d\n",dev,block,bh->b_count);return;}bh->b_dirt=0;bh->b_uptodate=0;brelse(bh);}/*计算block在数据区开始算起的数据逻辑块号(从1开始计数)。然后对逻辑块为图进行操作。复位对应的比特为。*/block -= sb->s_firstdatazone - 1 ;if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);panic("free_block: bit already cleared");}sb->s_zmap[block/8192]->b_dirt = 1;}int new_block(int dev){struct buffer_head * bh;struct super_block * sb;int i,j;/*得到超级块*/if (!(sb = get_super(dev)))panic("trying to get new block from nonexistant device");j = 8192;/*从8个位图中查找第一个空的block(也就是第一个为0的位)*/for (i=0 ; i<8 ; i++)if (bh=sb->s_zmap[i])if ((j=find_first_zero(bh->b_data))<8192)break;if (i>=8 || !bh || j>=8192)return 0;/*把对应的位置位*/if (set_bit(j,bh->b_data))panic("new_block: bit already set");bh->b_dirt = 1;/*计算真正的block号,记录到j中*/j += i*8192 + sb->s_firstdatazone-1;if (j >= sb->s_nzones)return 0;/*从缓冲区中验证新block块*/if (!(bh=getblk(dev,j)))panic("new_block: cannot get block");/*如果新块引用计数为1,出错*/if (bh->b_count != 1)panic("new block: count is != 1");/*把缓冲区n内容喔咕清0,并记录位最新数据,置位修改位,返回逻辑块号*/clear_block(bh->b_data);bh->b_uptodate = 1;bh->b_dirt = 1;brelse(bh);return j;}/*释放节点*/void free_inode(struct m_inode * inode){struct super_block * sb;struct buffer_head * bh;if (!inode)return;/*如果设备号为0,说明无用。清空该节点*/if (!inode->i_dev) {memset(inode,0,sizeof(*inode));return;}/*如果该节点还有其他程序引用,则出错*/if (inode->i_count>1) {printk("trying to free inode with count=%d\n",inode->i_count);panic("free_inode");}/*如果该节点链接数不为0,出错*/if (inode->i_nlinks)panic("trying to free inode with links");/*读取超级块*/if (!(sb = get_super(inode->i_dev)))panic("trying to free inode on nonexistent device");/*如果节点号小于1或者大于最大节点号,出错*/if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)panic("trying to free inode 0 or nonexistant inode");/*如果对应的节点位图的位不存在,出错*/if (!(bh=sb->s_imap[inode->i_num>>13]))panic("nonexistent imap in superblock");/*把对应的位图位清零*/if (clear_bit(inode->i_num&8191,bh->b_data))panic("free_inode: bit already cleared");/*置为脏*/bh->b_dirt = 1;/*节点清0*/memset(inode,0,sizeof(*inode));}struct m_inode * new_inode(int dev){struct m_inode * inode;struct super_block * sb;struct buffer_head * bh;int i,j;/*如果申请的空inode失败,返回0*/if (!(inode=get_empty_inode()))return NULL;/*获取超级块*/if (!(sb = get_super(dev)))panic("new_inode with unknown device");/*循环查找节点位图表*/j = 8192;for (i=0 ; i<8 ; i++)if (bh=sb->s_imap[i])if ((j=find_first_zero(bh->b_data))<8192)break;/*如果找到的节点超出范围,释放节点,返回null*/if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {iput(inode);return NULL;}/*把对应的位图位 置位*/if (set_bit(j,bh->b_data))panic("new_inode: bit already set");/*设置缓冲区为脏*/bh->b_dirt = 1;inode->i_count=1;  //设置引用数为1       inode->i_nlinks=1; // 设置链接数为1inode->i_dev=dev;  // 设置设备号inode->i_dirt=1;   // 设置脏inode->i_num = j + i*8192; //设置节点号/*设置节点时间*/inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;return inode;}

原创粉丝点击