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

/*把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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值