/*把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; // 设置链接数为1
inode->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;
}
linux-011中位图操作函数(申请释放节点,申请释放block)解析
最新推荐文章于 2023-06-02 16:10:31 发布