免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1102 | 回复: 0
打印 上一主题 下一主题

bitmap.c [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-14 16:39 |只看该作者 |倒序浏览

/*
* linux/fs/bitmap.c
*
* (C) 1991 Linus Torvalds
*/
/* bitmap.c contains the code that handles the inode and block bitmaps */
#include string.h>
#include linux/sched.h>
#include linux/kernel.h>
#define clear_block(addr) \
__asm__("cld\n\t" \
    "rep\n\t" \
    "stosl" \
    ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")//将指定地址(addr)处的一块1024字节内存清零
#define set_bit(nr,addr) ({\
register int res __asm__("ax"); \
__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;})// 置位指定地址开始的第nr 个位偏移处的比特位(nr 可以大于32!),返回原比特位(0 或1)
#define clear_bit(nr,addr) ({\
register int res __asm__("ax"); \
__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
res;})// 复位指定地址开始的第nr 位偏移处的比特位。返回原比特位的反码
#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;})// 从addr 开始寻找第1 个0 值比特位,并将其距离addr 的比特位偏移值返回
void free_block(int dev, int block)// 释放设备dev 上数据区中的逻辑块block
{
    struct super_block * sb;
    struct buffer_head * bh;
    if (!(sb = get_super(dev)))// 取指定设备dev 的超级块,如果指定设备不存在,则出错死机
        panic("trying to free block on nonexistent device");
    if (block  sb->s_firstdatazone || block >= sb->s_nzones)//若逻辑块号小于首个逻辑块号或者大于设备上总逻辑块数,则出错,死机
        panic("trying to free block not in datazone");
    bh = get_hash_table(dev,block);//考虑到里程竞争的情况,,利用hash表在高速缓冲中寻找给定设备和指定块的缓冲区块
    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;/* 0-clean,1-dirty *///修改标志0为未修改,1为修改
        bh->b_uptodate=0;//更新标志,缓冲区上的数据是否为块上的数据同步,1为与硬盘上的数据同步一样
        brelse(bh);// 本任务释放指定的缓冲块区,
    }//以下操作为,复位blok在逻辑块位图中的比特位
    block -= sb->s_firstdatazone - 1 ;// 计算block 在数据区开始算起的数据逻辑块号(从1 开始计数)
    if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {// 复位指定地址开始的第nr 位偏移处的比特位,一个缓冲块有1024字节,8192比特位
        printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
        panic("free_block: bit already cleared");
    }
    sb->s_zmap[block/8192]->b_dirt = 1;// 置相应逻辑块位图所在缓冲区已修改标志, 0-clean,1-dirty 修改标志0为未修改,1为修改
}
int new_block(int dev)//向设备dev 申请一个逻辑块(盘块,区块),返回逻辑块号(盘块号)
{
    struct buffer_head * bh;
    struct super_block * sb;
    int i,j;
    if (!(sb = get_super(dev)))// 取指定设备dev 的超级块,如果指定设备不存在,则出错死机
        panic("trying to get new block from nonexistant device");
    j = 8192;//一块的比特位,1k=1024字节==1024*8比特位
    for (i=0 ; i8 ; i++)//寻找全部8块逻辑块位图,每块为1K(1024*8==8192)比特位
        if (bh=sb->s_zmap)
            if ((j=find_first_zero(bh->b_data))8192)// 从addr 开始寻找第1 个0 值比特位,并将其距离addr 的比特位偏移值返回
                break;
    if (i>=8 || !bh || j>=8192)// 如果全部扫描完还没找到(i>=8 或j>=8192)或者位图所在的缓冲块无效(bh=NULL)则 返回0
        return 0;
    if (set_bit(j,bh->b_data))// 置位指定地址开始的第nr 个位偏移处的比特位(nr 可以大于32!),返回原比特位(0 或1)
        panic("new_block: bit already set");
    bh->b_dirt = 1;/* 0-clean,1-dirty *///修改标志0为未修改,1为修改
    j += i*8192 + sb->s_firstdatazone-1;//将J转化为逻辑块号
    if (j >= sb->s_nzones)// sb->s_nzones为总的逻辑块数
        return 0;
    if (!(bh=getblk(dev,j)))//然后在高速缓冲区为该设备指定的逻辑块号取一缓冲块区
        panic("new_block: cannot get block");
    if (bh->b_count != 1)// 新块的引用计数应为1,
        panic("new block: count is != 1");
    clear_block(bh->b_data);//将新申请遥逻辑块区清0,将指定地址(addr)处的一块1024字节内存清零
    bh->b_uptodate = 1;//更新标志,缓冲区上的数据是否为块上的数据同步,1为与硬盘上的数据同步一样
    bh->b_dirt = 1;/* 0-clean,1-dirty *///修改标志0为未修改,1为修改
    brelse(bh);// 本任务释放指定的缓冲块区,(这里有点不明白,为什么刚申请了缓冲块,又给释放了呢?)
    return j;
}
void free_inode(struct m_inode * inode)// 释放指定的i 节点
{
    struct super_block * sb;
    struct buffer_head * bh;
    if (!inode)// 如果i 节点指针=NULL,则退出
        return;
    if (!inode->i_dev) {// i 节点所在的设备,如果为空则说明此节点没有被使用,用0填充所有内存
        memset(inode,0,sizeof(*inode));//用0填充此节点的所有内存
        return;
    }
    if (inode->i_count>1) {// 如果此i 节点还有其它程序引用,则不能释放,说明内核有问题,死机
        printk("trying to free inode with count=%d\n",inode->i_count);
        panic("free_inode");
    }
    if (inode->i_nlinks)// 如果文件目录项连接数不为0,则表示还有其它文件目录项在使用该节点,不应释放,而应该放回
        panic("trying to free inode with links");
    if (!(sb = get_super(inode->i_dev)))// 取i 节点所在设备的超级块,并测试设备是否存在
        panic("trying to free inode on nonexistent device");
    if (inode->i_num  1 || inode->i_num > sb->s_ninodes)// 如果i 节点号小于0 或大于该设备上i 节点总数,则出错
        panic("trying to free inode 0 or nonexistant inode");
    if (!(bh=sb->s_imap[inode->i_num>>13]))// 如果该i 节点对应的节点位图不存在,则出错
        panic("nonexistent imap in superblock");
    if (clear_bit(inode->i_num&8191,bh->b_data))// 复位指定地址开始的第nr 位偏移处的比特位。返回原比特位的反码
        printk("free_inode: bit already cleared.\n\r")
    bh->b_dirt = 1;// 置i 节点位图所在缓冲区已修改标志,并清空该i 节点结构所占内存区
    memset(inode,0,sizeof(*inode));//释放此节点
}
struct m_inode * new_inode(int dev)// 为设备dev 建立一个新i 节点。返回该新i 节点的指针
{// 在内存i 节点表中获取一个空闲i 节点表项,并从i 节点位图中找一个空闲i 节点。
    struct m_inode * inode;
    struct super_block * sb;
    struct buffer_head * bh;
    int i,j;
    if (!(inode=get_empty_inode()))// 从内存i 节点表(inode_table)中获取一个空闲i 节点项(inode)
        return NULL;
    if (!(sb = get_super(dev)))// 取i 节点所在设备的超级块,并测试设备是否存在
        panic("new_inode with unknown device");
    j = 8192;//一块的比特位,1k=1024字节==1024*8比特位
    for (i=0 ; i8 ; i++)//寻找全部8块节点位图,每块为1K(1024*8==8192)比特位
        if (bh=sb->s_imap)
            if ((j=find_first_zero(bh->b_data))8192)// 从addr 开始寻找第1 个0 值比特位,并将其距离addr 的比特位偏移值返回
                break;
    if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {// 如果全部扫描完还没找到,或者位图所在的缓冲块无效(bh=NULL)则 返回0,退出
        iput(inode);//放回刚才申请的inode节点
        return NULL;
    }
    if (set_bit(j,bh->b_data))//将相应的i节点位图置位,置位指定地址开始的第nr 个位偏移处的比特位(nr 可以大于32!),返回原比特位(0 或1),如果已经置位,则出错
        panic("new_inode: bit already set");
    bh->b_dirt = 1;/* 0-clean,1-dirty *///修改标志0为未修改,1为修改
    inode->i_count=1;// i 节点被使用的次数,0 表示该i 节点空闲。
    inode->i_nlinks=1;// 文件目录项链接数。
    inode->i_dev=dev;// i 节点所在的设备号。
    inode->i_uid=current->euid;// 用户id(文件拥有者标识符)。
    inode->i_gid=current->egid;// 组id(文件拥有者所在的组)。
    inode->i_dirt=1;// 已修改(脏)标志。
    inode->i_num = j + i*8192;// i 节点号。
    inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;// 修改时间(自1970.1.1:0 算起,秒)。
    return inode;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/90876/showart_2027466.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP