免费注册 查看新帖 |

Chinaunix

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

JBD2(journaling block device 2)系统分析(六) [复制链接]

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

                上一节,我们讲了怎么初始化journal对像和日志分区的检查,其中说到一个函数
journal = jbd2_journal_init_dev(bdev, sb->s_bdev, start, len, blocksize);
这个函数就是初始化日志分区的。
上面的参数依次是:日志分区描述结构体,主分区描述结构体,主分区数据起始的block编号,主分区的bock数,和主分区的block的大小。
这个函数的实现在fs/jbd2/journal.c(1036)

/* jbd2_journal_init_dev and jbd2_journal_init_inode:
*
* Create a journal structure assigned some fixed set of disk blocks to
* the journal. We don't actually touch those disk blocks yet, but we
* need to set up all of the mapping information to tell the journaling
* system where the journal blocks are.
*
*/
/* jbd2_journal_init_dev 和 jbd2_journal_init_inode的功能都是一样的,
    就是创建journal结构体,并且给它一些固定的成员赋值,主要是主分区的
    一些信息。我们并没有进行实际的硬盘读写操作,只是让日志系统知道真正
    的日志信息数据块在哪里。
*/

/** 下面这段就不翻译了,日志开始已经过过这些参数的意思了。
* journal_t * jbd2_journal_init_dev() - creates and initialises a journal structure
* @bdev: Block device on which to create the journal
* @fs_dev: Device which hold journalled filesystem for this journal.
* @start: Block nr Start of journal.
* @len: Length of the journal in blocks.
* @blocksize: blocksize of journalling device
*
* Returns: a newly created journal_t *
*
* jbd2_journal_init_dev creates a journal which maps a fixed contiguous
* range of blocks on an arbitrary block device.
*
*/
journal_t * jbd2_journal_init_dev(struct block_device *bdev,
            struct block_device *fs_dev,
            unsigned long long start, int len, int blocksize)
{
    // 给journal_t结构体分配空间,并初始化一些成员变量,主要是等待列表
    // 和一些固定的东西,它的实现在journal.c(971)行,那里面有两个函数要
    // 简单说明一下,jbd2_journal_init_revoke:这个函数创建和初始化这个
    // 日志的撤销表,就是当一个数据块已经正确写到主设备上了,就要把这块
    // 数据从日志系统中删除,因为不是立即删除,所以要放在一个表里,等待。
    // 还有另一个函数是journal_init_stats:这个函数初始化journal的状态,
    // 并创建一个历史列表来记录100个已经完成了的transaction.
    journal_t *journal = journal_init_common();
    struct buffer_head *bh;
    char *p;
    int n;
    if (!journal)
        return NULL;
    /* journal descriptor can store up to n blocks -bzzz */
    journal->j_blocksize = blocksize; // 记录主分区的block大小。
    //初始化主分区在/proc/fs/jbd2/sdax 的目录和里面的info,history.
    jbd2_stats_proc_init(journal);
    // 计算一个block里能在放多少个buffer_head的描述符。并创建相应个数的
    // buffer_head的指针空间。
    n = journal->j_blocksize / sizeof(journal_block_tag_t);
    journal->j_wbufsize = n;
    journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
    if (!journal->j_wbuf) {
        printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
            __func__);
        goto out_err;
    }
    journal->j_dev = bdev;
    journal->j_fs_dev = fs_dev;
    journal->j_blk_offset = start;
    journal->j_maxlen = len;
    /*    下面就是根据主分区来生成日志的名字,就是设备名加分区名,如“sda8”
    */
    bdevname(journal->j_dev, journal->j_devname);
    p = journal->j_devname;
    while ((p = strchr(p, '/')))
        *p = '!';
    // 从日志分区的第一个数据块读出一个块的数据。这个块就是日志分区的
    // super_block,当然实际名称是journal_superblock_t,定义在include/
    // linux/jbd2.h(212)
    bh = __getblk(journal->j_dev, start, journal->j_blocksize);
    if (!bh) {
        printk(KERN_ERR
         "%s: Cannot get buffer for journal superblock\n",
         __func__);
        goto out_err;
    }
    journal->j_sb_buffer = bh;
    journal->j_superblock = (journal_superblock_t *)bh->b_data;
    return journal;
out_err:
    jbd2_stats_proc_exit(journal);
    kfree(journal);
    return NULL;
}
接下来我们再看看jbd2_stats_proc_init,其定义在journal.c(927)

/*这个函数就是这么寥寥几行,真让人怀疑它的能力,但你有所不知道,往往最简单的东西
后面却暗藏着玄机,或叫什么冰山一角之类的吧。且让我说说它的功能。确实很简单,就
是在/proc/fs/jbd2目录下根据设备号生成的名称创建一个目录,比如sda8:8(因为我的机器 没有独立分区来记录易日志,而是一个目录,所以在sda8后加了一个8,表示这个分区里的第8个inode是用来记录日志的,相关代码在journal.c/1112),关于里面的proc_jbd2_stats这个变量如果你的大脑内存比较大应该还记得在journal_init函数里有一个
jbd2_create_jbd_stats_proc_entry吧,就是在那创建的这个目录。这里再深入就涉及/proc文件系统了,但是/proc系统作为内核对外层应该的一个窗口,我就不得不哆嗦几句了。创建了相应的目录后,再创建两个文件,一个是history,一个是info,到这里,应该怎么第三节里讲的那两个文件是怎么来的了吧,至于怎么显示出那些信息来的,放在下节讲吧,哥们累了,要睡了Zzzz*/
static void jbd2_stats_proc_init(journal_t *journal)
{
    journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
    if (journal->j_proc_entry) {
        proc_create_data("history", S_IRUGO, journal->j_proc_entry,
                 &jbd2_seq_history_fops, journal);
        proc_create_data("info", S_IRUGO, journal->j_proc_entry,
                 &jbd2_seq_info_fops, journal);
    }
}
               
               

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP