Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2036400
  • 博文数量: 610
  • 博客积分: 11499
  • 博客等级: 上将
  • 技术积分: 5511
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-12 19:27
文章分类

全部博文(610)

文章存档

2016年(5)

2015年(18)

2014年(12)

2013年(16)

2012年(297)

2011年(45)

2010年(37)

2009年(79)

2008年(101)

分类:

2012-11-16 01:19:23

原文地址:exofs源码分析 作者:crote

格式化源码: mkexofs.c mkexofs_main.c mkexofs.h              (~/open-osd/usr)

格式化步骤:

1.       调用osd_open()(~/open-osd/lib/osddev.c)打开对应的osd设备,并将打开的osd设备信息保存于类型为struct osd_dev的数组中。

2.       调用mkexofs.format()(~/open-osd/usr)根据一些选项对打开的osd设备进行格式化。

3.       调用osd_closd()(~/open-osd/lib/osddev.c)关闭之前打开的osd设备。

 

格式化过程中对每个OSD设备执行如下操作:

1.       OSD设备进行格式化,请求设备服务器格式化整个OSD,即删除所有的用户对象,删除处0号分区以外的所有分区对象,而后按照约定重新设置根对象和第0号分区对象的属性。格式化的目的是创建一个新的OSD逻辑单元。(由函数_format()实现)

2.       在每个OSD设备上创建分区对象(由函数mkfs_one()调用create_partition()实现),分区对象的ID号为先前命令中传入的PID(这说明一个分区上就放着一个文件系统,但是这个分区跨不同的对象设备?)

3.       创建超级块对象,对象号为{ pid, EXOFS_SUPER_ID},其中EXOFS_SUPER_ID0x10000(由函数mkfs_one()调用create ()实现)

4.       创建根目录对象,对象号为{ pid, EXOFS_ROOT_ID},其中EXOFS_ROOT_ID0x10002. (由函数mkfs_one()调用create ()实现)

5.       在设备表对象中写入设备表。具体步骤如下:

a)         调用create()创建设备表对象,设备表对象的对象号为{pid, EXOFS_DEVTABLE_ID},其中EXOFS_DEVTABLE_ID0x10001

b)        调用_make_credential()以不做检验方式初始化设备表对象的权能,也就是创建证书。

c)         根据先前输入的参数创建并初始化设备表结构体struct exofs_device_table,并将其写入到设备表对象中取。

6.       在超级块对象中写入超级块是通过调用函数write_super()实现的,该函数调用_make_credential()以不做检验方式初始化超级块对象的权能,也就是创建证书。初始化超级块数据结构struct exofs_fscb,并将其写入超级块对象。

7.       在根目录对象中写入根目录信息是通过调用函数write_rootdir()实现的,该函数调用_make_credential()以不做检验方式初始化根目录对象的权能,也就是创建证书。初始化根目录项数据结构struct exofs_dir_entry,并将其写入根目录对象。

8.       在根目录项对象中写入根inodes是通过调用函数set_inode()实现的,inode信息是以结构体struct exofs_fcb进行描述。set_inode()函数具体步骤如下:

a)         初始化一个struct exofs_fcb结构体

b)        调用函数osd_start_request()分配一个osd请求。

c)         调用_make_credential()创建证书,其实就是调用osd_sec_init_nosec_doall_caps()以不做检验方式(no security)初始化根对象权能。

d)        调用osd_req_set_attributes()获取对象属性(实际只是进行编码)

e)         inode(结构体struct exofs_fcb)以属性列表的形式添加到osd请求中。

f)         调用kick_it()执行请求,调用osd_end_request()释放资源。

       

内核态源码: 

磁盘上的超级块:

  1. //.common.h
  2. struct exofs_fscb {
  3.     __le64 s_nextid;    /* Highest object ID used *///已被使用的最大到对象ID
  4.     __le64 s_numfiles;    /* Number of files on fs *///文件系统上的文件数
  5.     __le32    s_version;    /* == EXOFS_FSCB_VER *///超级块版本,直接为EXOFS_FSCB_VER
  6.     __le16 s_magic;    /* Magic signature */    //文件系统魔数
  7.     __le16 s_newfs;    /* Non-zero if this is a new fs *///如果这是一个新的文件系统,则非零

  8.     /* From here on it's a static part, only written by mkexofs */
  9.     __le64    s_dev_table_oid; /* Resurved, not used */    //保留
  10.     __le64    s_dev_table_count; /* == 0 means no dev_table *///如果没有设备列表,则为0
  11. } __packed;

在挂载到时候,调用exofs_fill_super()(super.c )osd设备上读取上述信息来初始化内存中的超级块描述符struct super_block

 

超级块操作:

点击(此处)折叠或打开

  1. // ./super.c
  2. static const struct super_operations exofs_sops = {
  3.     .alloc_inode = exofs_alloc_inode,            //对于一个给定的超级块,创建并初始化一个新的inode对象
  4.     .destroy_inode = exofs_destroy_inode,        //释放一个给定的超级块
  5.     .write_inode = exofs_write_inode,        //当某个inode为脏(被修改了),就有VFS进行调用。这里如果是日志文件系统,则调用该函数进行日志的更新?
  6.     .evict_inode = exofs_evict_inode,        //从磁盘删除一个inode
  7.     .put_super = exofs_put_super,            //在卸载过程中由VFS调用来释放一个给定到超级块对象,调用者必须持有s_lock锁
  8.     .write_super = exofs_write_super,        //用一个给定的超级块更新磁盘上的超级块,VFS利用其来将内存中的超级块同步到磁盘,调用者必须持有s_lock锁
  9.     .sync_fs    = exofs_sync_fs,                //将文件系统元数据同步到磁盘(osd设备上)
  10.     .statfs = exofs_statfs,            //由VFS调用来获取文件系统的统计数据并保存与结构体struct statfs中
  11. };

这里有部分域为空,则调用后有可能是调用一个通用的操作函数,或者什么也不做,这个取决于具体操作。

在挂载到时候,调用exofs_fill_super()(super.c )来初始化超级块操作。


磁盘上的inode结构:

点击(此处)折叠或打开

  1. // ./common.h
  2. struct exofs_fcb {
  3.     __le64 i_size;            /* Size of the file */    //文件大小
  4.     __le16 i_mode;     /* File mode */    //文件访问模式
  5.     __le16 i_links_count;     /* Links count */    //文件链接数
  6.     __le32 i_uid;     /* Owner Uid */    //文件拥有者id
  7.     __le32 i_gid;     /* Group Id */        //文件组id
  8.     __le32 i_atime;     /* Access time */    //文件访问时间
  9.     __le32 i_ctime;     /* Creation time */    //文件创建时间
  10.     __le32 i_mtime;     /* Modification time */    //文件修改时间
  11.     __le32 i_flags;     /* File flags (unused for now)*/    //文件系统标志
  12.     __le32 i_generation;     /* File version (for NFS) */    //文件版本(对应于NFS)
  13.     __le32 i_data[EXOFS_IDATA];    /* Short symlink names and device #s */    //对应的osd设备id
  14. };

当文件被访问时,也就是调用open()函数时,通过读取磁盘上的inode结构初始化内存中的inode结构体 struct inode

具体一点就是根据索引节点号获取该索引节点时,调用函数exofs_get_inode()(inode.c),或者将内存中的索引节点刷新到磁盘时,调用函数exofs_update_inode()(inode.c)


inode操作:

目录类型的inode操作:

点击(此处)折叠或打开

  1. // ./namei.c
  2. const struct inode_operations exofs_dir_inode_operations = {

  3.     .create     = exofs_create,
  4.         //由open(),creat()系统调用调用,对一个给定的初始化访问模式创建一个新的inode
  5.     .lookup     = exofs_lookup,
  6.         //根据由dentry给定的文件名找到对应的inode
  7.     .link     = exofs_link,
  8.             //由link()系统调用调用,对一个给定的名字创建硬链接
  9.     .unlink     = exofs_unlink,
  10.         //由unlink()系统调用调用,删除该链接对应到inode
  11.     .symlink    = exofs_symlink,
  12.         //由symlink()系统调用调用,创建一个符号链接
  13.     .mkdir     = exofs_mkdir,
  14.         //由mkdir()系统调用调用,创建目录
  15.     .rmdir     = exofs_rmdir,
  16.             //删除目录,由rmdir()系统调用调用
  17.     .mknod     = exofs_mknod,
  18.         //创建特殊文件如设备文件、有名管道和socket,由mknod()系统调用调用
  19.     .rename     = exofs_rename,        //改名

  20.     .setattr    = exofs_setattr,
  21.         //在inode被修改后,由notify_change()来通知一个”change event”
  22. };

在从磁盘读取一个inode后,需要根据类型初始化对其的操作集,调用exofs_iget()(inode.c)

当创建一个目录时,同时也会创建一个内存inode并初始化对其的操作集,调用exofs_mkdir()(namei.c)

特殊inode节点对应的操作:

点击(此处)折叠或打开

  1. // namei.c
  2. const struct inode_operations exofs_special_inode_operations = {

  3.     .setattr    = exofs_setattr,
  4.     //在inode被修改后,由notify_change()来通知一个”change event”
  5. };

在从磁盘读取一个inode后,需要根据类型初始化对其的操作集,调用exofs_iget()(inode.c)

普通文件类型的inode操作:

点击(此处)折叠或打开

  1. // ./file.c
  2. const struct inode_operations exofs_file_inode_operations = {

  3.     .setattr    = exofs_setattr,
  4.     //在inode被修改后,由notify_change()来通知一个”change event”
  5. };

在从磁盘读取一个inode后,需要根据类型初始化对其的操作集,调用exofs_iget()(inode.c)

当创建一个普通文件时,同时也会创建一个内存inode并初始化对其的操作集,调用exofs_create()(namei.c)

符号链接inode对应的操作:

 点击(此处)折叠或打开

  1. // symlink.c
  2. const struct inode_operations exofs_symlink_inode_operations = {

  3.     .readlink    = generic_readlink,
  4.                 //将符号链接指向的文件的文件名拷贝到缓冲区,由readlink()系统调用调用
  5.     .follow_link    = page_follow_link_light,
  6.     //将符号链接转换为其所指的inode,并将inode信息保存于nameidata中。
  7.     .put_link    = page_put_link,
  8.             //在follow_link()调用之后,调用该函数进行清除工作。
  9. };

在从磁盘读取一个inode后,需要根据类型初始化对其的操作集,调用exofs_iget()(inode.c)

当创建一个普通文件时,同时也会创建一个内存inode并初始化对其的操作集,调用exofs_symlink()(namei.c)

磁盘上的目录项

点击(此处)折叠或打开

  1. // common.h
  2. struct exofs_dir_entry {
  3.     __le64        inode_no;        /* inode number */    //索引节点数
  4.     __le16        rec_len;        /* directory entry length */        //目录项长度
  5.     u8        name_len;        /* name length */            //名字长度
  6.     u8        file_type;        /* umm...file type */                //文件类型
  7.     char        name[EXOFS_NAME_LEN];    /* file name */    //文件名
  8. };


文件操作:

目录类型的文件的操作:

点击(此处)折叠或打开

  1. // ./dir.c

  2. const struct file_operations exofs_dir_operations = {

  3.        .llseek = generic_file_llseek,

  4.        .read = generic_read_dir,

  5.        .readdir = exofs_readdir,

  6. };

在从磁盘读取一个inode后,需要根据类型初始化对其所对应文件的操作集,调用exofs_iget()(inode.c)

当创建一个普通文件时,同时也会创建一个内存inode并初始化对其所对应的文件的操作集,调用exofs_mkdir()(namei.c)

普通文件的操作: 

点击(此处)折叠或打开

  1. // ./file.c

  2. const struct file_operations exofs_file_operations = {

  3.        .llseek = generic_file_llseek,

  4.        .read = do_sync_read,

  5.        .write = do_sync_write,

  6.        .aio_read = generic_file_aio_read,

  7.        .aio_write = generic_file_aio_write,

  8.        .mmap = generic_file_mmap,

  9.        .open = generic_file_open,

  10.        .release = exofs_release_file,

  11.        .fsync = exofs_file_fsync,

  12.        .flush = exofs_flush,

  13.        .splice_read = generic_file_splice_read,

  14.        .splice_write = generic_file_splice_write,

  15. };

在从磁盘读取一个inode后,需要根据类型初始化对其所对应的文件的操作集,调用exofs_iget()(inode.c)

当创建一个普通文件时,同时也会创建一个内存inode并初始化对其所对应的文件的操作集,调用exofs_create()(namei.c)

 

特定文件系统类型描述:

点击(此处)折叠或打开

  1. // ./super.c

  2. static struct file_system_type exofs_type = {

  3.        .owner = THIS_MODULE,

  4.        .name = "exofs",

  5.        .mount = exofs_mount, //文件系统挂载函数

  6.        .kill_sb = generic_shutdown_super, //终止访问超级块

  7. };

在文件系统模块插入初始化调用register_filesystem()对该文件系统注册。在文件系统模块删除时调用unregister_filesystem()对该文件系统注销。

 

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