免费注册 查看新帖 |

Chinaunix

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

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

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

        jbd2所以的文件在linux-kernel(2.6.30,我所用的是kernel2.6.30)/fs/jbd2目录下,当然还有一个文件在/include/linux下的jbd2.h。
下面来看看这个模块一共多少代码,
lan@lan-laptop:~/linux-2.6.30/fs/jbd2$ wc -l *.c
   760 checkpoint.c
  1066 commit.c
  2383 journal.c
   745 recovery.c
   714 revoke.c
  2180 transaction.c
        7848 total
就七千多行代码,这相对于有1000多万行的linux内核来说,真是让我们做梦能笑出声来。其它的先不管,按照fudan_abc的说法,先看看Makefile文件。
lan@lan-laptop:~/linux-2.6.30/fs/jbd2$ cat Makefile
#
# Makefile for the linux journaling routines.
#

obj-$(CONFIG_JBD2) += jbd2.o

jbd2-objs := transaction.o commit.o recovery.o checkpoint.o revoke.o journal.o

除了注释就两行有用的:
obj-$(CONFIG_JBD2) += jbd2.o这行的意思是你要将jbd2模块以什么样的方式编译到内核中,有三种选择方式(Y与内核一起编译,M以模块方式编译,N不编译,当内核有Ext4或是OCFS2文件系统时不能没有jbd2)。

jbd2-objs := transaction.o commit.o recovery.o checkpoint.o revoke.o journal.o
这行的意思是jbd2所需的目标文件,一共有六个文件,这是一个make的隐式规则,这六个.o文件对应该的是同名的.c文件,就是刚才统计行数的那六个文件。当然还有一个jbd2.h在include/linux目录下,是其它(Ext4等模块)用的。

Jbd2模块的入口在journal.c文件里,看最后三行,
MODULE_LICENSE("GPL");
module_init(journal_init);
module_exit(journal_exit);
写过Linux内核驱动,哪怕是最简单的经典的printk(“hello world\n”);都知道这是三行意思。module_init(journal_init)这个表示jbd2这个模块的入口,它通过执行journal_init这个函数来实现,module_exit(journal_exit)表示这个jbd2这个模块卸载时要执行的函数journal_exit.

看journal.c的第2352行。


static int __init journal_init(void)
{
    int ret;
    BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024);
    ret = journal_init_caches();
    if (ret == 0) {
        jbd2_create_debugfs_entry();
        jbd2_create_jbd_stats_proc_entry();
    } else {
        jbd2_journal_destroy_caches();
    }
    return ret;
}

所有的模块入口函数都是一个模样,哈哈,连空行也就12行,让我们一行一行的看。
2356行是判断journal_superblock_s这个结构体的大小是不是1024字节,如果不是,则迫使编译器报一个编译错误。journal_superblock_s在include/linux/jbd2.h里,定义如下(209行开始)
/*
* The journal superblock. All fields are in big-endian byte order.
*/
typedef struct journal_superblock_s
{
/* 0x0000 */
    journal_header_t s_header;
/* 0x000C */
    /* Static information describing the journal */
    __be32    s_blocksize;        /* journal device blocksize */
    __be32    s_maxlen;        /* total blocks in journal file */
    __be32    s_first;        /* first block of log information */
/* 0x0018 */
    /* Dynamic information describing the current state of the log */
    __be32    s_sequence;        /* first commit ID expected in log */
    __be32    s_start;        /* blocknr of start of log */
/* 0x0020 */
    /* Error value, as set by jbd2_journal_abort(). */
    __be32    s_errno;
/* 0x0024 */
    /* Remaining fields are only valid in a version-2 superblock */
    __be32    s_feature_compat;    /* compatible feature set */
    __be32    s_feature_incompat;    /* incompatible feature set */
    __be32    s_feature_ro_compat;    /* readonly-compatible feature set */
/* 0x0030 */
    __u8    s_uuid[16];        /* 128-bit uuid for journal */
/* 0x0040 */
    __be32    s_nr_users;        /* Nr of filesystems sharing log */
    __be32    s_dynsuper;        /* Blocknr of dynamic superblock copy*/
/* 0x0048 */
    __be32    s_max_transaction;    /* Limit of journal blocks per trans.*/
    __be32    s_max_trans_data;    /* Limit of data blocks per trans. */
/* 0x0050 */
    __u32    s_padding[44];
/* 0x0100 */
    __u8    s_users[16*48];        /* ids of all fs'es sharing the log */
/* 0x0400 */
} journal_superblock_t;
正好是0x400=1024字节,如果不等于1024字节,那当然就出错了。接下来调用了一个journal_init_caches(),这个函数所做功能就是初化jbd2所需要的cache,这里先放下,以后再慢慢说,不管怎么样,这个函数如果成功就反回0,否返回非0,一般是负数,当然也有些函数不是返回0表示成功,而是返回一个有效的指针地址;还有一些十分变态的函数,返回非0表示成功,等遇到这样的函数我再狠狠的骂它一顿。
如果journal_init_caches()返回0,那就执行 jbd2_create_debugfs_entry()jbd2_create_jbd_stats_proc_entry()当然,在release版本中,jbd2_create_debugfs_entry()是一个空函数,它只是为了调试用的,一调试完成,它也就没有用了,卸磨杀驴不是很多人惯用的招数么?那么jbd2_create_jbd_stats_proc_entry()又做的是什么呢?我们还是来看看它的代码(journal.c/2285)

#ifdef CONFIG_PROC_FS
#define JBD2_STATS_PROC_NAME "fs/jbd2"
static void __init jbd2_create_jbd_stats_proc_entry(void)
{
    proc_jbd2_stats = proc_mkdir(JBD2_STATS_PROC_NAME, NULL);
}
static void __exit jbd2_remove_jbd_stats_proc_entry(void)
{
    if (proc_jbd2_stats)
        remove_proc_entry(JBD2_STATS_PROC_NAME, NULL);
}
#else
#define jbd2_create_jbd_stats_proc_entry() do {} while (0)
#define jbd2_remove_jbd_stats_proc_entry() do {} while (0)
#endif
一看它的名字都能知道,其实它是在linux系统里的/proc/fs创建一个目录叫jbd2.如果你的系统有分区是ext4系统,那么就会看到
lan@lan-laptop:~$ ls /proc/fs
ext4 jbd2 nfsd
那个jbd2目录就是这个函数的功劳。这里也能看到jbd2_remove_jbd_stats_proc_entry(void)这个函数,它就负责把这目录在jbd2卸载的时候把这个目录删除的,同时你也看到#ifdef CONFIG_PROC_FS这个宏,这个宏开表示我们的系统要/proc这个文件系统,如果没有开,那么就不会有/proc这个目录,更不会有fs/jbd2,所以在#else后的函数是空实现。
如果journal_init_caches()返回一个非0,就会执行jbd2_journal_destroy_caches();
来清除(可能)已经创建的cache.然后把ret返回,因为是非0,所以系统就知道这个模块在初始化的时候出错,就不会把模块调起来。


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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP