Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1482247
  • 博文数量: 181
  • 博客积分: 3308
  • 博客等级: 中校
  • 技术积分: 2227
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-03 12:03
个人简介

我是zoro

文章分类

全部博文(181)

文章存档

2015年(1)

2013年(35)

2012年(39)

2011年(50)

2010年(56)

分类: LINUX

2011-08-09 18:21:46

/*
 * 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 ; i<8 ; i++)//寻找全部8块逻辑块位图,每块为1K(1024*8==8192)比特位

        if (bh=sb->s_zmap[i])
            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 ; i<8 ; i++)//寻找全部8块节点位图,每块为1K(1024*8==8192)比特位

        if (bh=sb->s_imap[i])
            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;
}

转自http://shuwei.bian.blog.163.com/blog/static/142629666201022361139420/
阅读(1684) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~