Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40696
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2015-06-17 14:56
文章分类

全部博文(9)

文章存档

2015年(9)

我的朋友

分类: LINUX

2015-06-17 14:59: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);
    }
}

阅读(1311) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~