引言
什么是UBIFS文件系统
UBIFS是UBI file system的简称,用于裸的flash设备,作为jffs2的后继文件系统之一。UBIFS通过UBI子系统处理与MTD设备之间动作。UBIFS文件系统更适合MLCNAND FLASH。需要注意的是UBIFS并不是为SSD,MMC,SD,Compact Flash等之类的基于flash的存储设备,其是针对于裸flash设备。
裸flash有以下特点:
l 其包含的块被称为可擦除块,而对于SSD这类的设备,并无可擦除块的概念,取而代之的是扇区的概念。
l 包括读、写、擦除可擦除块三种操作。
l 硬件并不管理坏的可擦除块,而SSD之类的设备则具有专门的控制器处理坏块。
l 可擦除块的读写寿命从几千到几十万之间不等。
图0.1中给出的设备是MMC、SD类型的,该设备具有flash转换层的硬件控制器,该硬件控制器的损耗平衡算法属于商业秘密,华为的dorado 系列高端存储器的文档对其损耗平衡(动态和静态)原理讲解的非常透彻,感兴趣的可以自己找找。对于UBIFS使用的场景,通常只有NANDFLASH那一个模块,其和控制器的接口通常是专门的NAND flash接口。由于这类设备的速率比较慢,所以通常用在相对而言比较低端的嵌入式设备,追求加载速度快一点嵌入式设备通常会选择使用emmc存储器,其文件系统通常会选择UFS。
图0.1 具有flash转换层的设备
UBI/UBIFS 协议栈
图0.2 UBIFS实现的协议栈
MTD(Memory Technology Devices)对闪存存储器提供了一个抽象,隐藏了特定flash的独特之处,提供统一的API存取各种类型的flash。
MTD在内核层的API是struct mtd_device而用户空间的API接口是/dev/mtd0,这些接口提供了设备信息,读写可擦除块,擦除一个可擦除块,标记一个可擦除块是坏块,检查可擦除块是否是坏块。MTD的API并不隐藏坏的可擦除块也不做任何损耗平衡。
UBI(Unsorted Block Images)的内核API是include/mtd/ubi-user.h,用户空间的则是/dev/ubi0,提供损耗平衡,隐藏坏块,允许运行时容量创建、删除和修改,有点类似LVM功能。UBI线性扩展,在初始化时会读取所有的可擦除块头,所以当flash容量越大,初始化所花费的时间越多,但是就可扩展性而言比JFFS2要好很多。
LEB(logic eraseblock),PEB(physical erase block);将LEB映射到PEB,任何一个LEB可能映射到任何一个PEB,可擦除块头存储的是映射信息以及擦除计数值。
图0.3 UBI基本思想
UBI坏的可擦除块处理:
l 为坏的可擦除块预留1%的PEB
l 如果一个PEB变成坏块,则相应的LEB会被映射到一个好的PEB中
l I/O错处处理对上层并未隐藏。
写错误处理
假设用户写数据到LEB0可擦除块,选择一个好的PEB可擦除块(这里假设选择PEB4)来恢复数据,恢复数据实际上就是将数据拷贝到PEB4,然后重新映射LEB0到PEB4,映射完毕后将新数据再次写入PEB4,这是恢复就完成了,将回到UBI层,后台会将PEB1标记为坏块。
图0.4 写错误处理示例
原子改变LEB
这对UBIFS非常重要,假设LEB0需要被原子改变,这一过程是这样的:
首先选择一个合适的PEB块,加入这里选择了PEB0,然后向这个块写入新数据,写入完成后需要将原始映射PEB4解映射同时将LEB0映射到PEB0,这是就完成了原子更新操作返回UBI层,但是PEB4的数据会被后台擦除。
图0.5 原子改变LEB
对UBI底层的操作有了一些了解后,可以开始UBIFS的介绍了,首先UBIFS并不关系可擦除坏块了,这一信息依赖于UBI层,损耗平衡依赖于UBI层而不是UBIFS,LEB的更改是原子性的。
UBIFS文件索引
索引允许查找任何数据片段的物理地址。索引采用B+2的结构,图中右上半部分,只有叶子节点包含数据,数的扇出可配,缺省值是8。UBIFS的索引在flash上存储和维护。
图0.6 UBIFS索引
UBIFS日志
日志比较小,为节省功耗只扫描日志并不扫描flash所有数据,这一结果会让挂载很快完成。文件系统所有更改将被日志记录,索引信息只在内存修改,并不在flash上修改。
主节点存在于LEB1和LEB2,这两个块存储的是一样的,用于备份恢复之用,主节点指向根索引,主分区在挂载时可以很快被找到。
图0.7 索引和UBIFS的关系
超级块
超级块存储在LEB0位置处,对于UBIFS文件系统只读,但是可以被用户空间工具修改,存储如索引树扇出等一些配置信息,缺省使用zlib或者LZO进行压缩,在挂载该文件系统时,UBIFS的mount方法将被调用读取该超级块。
树节点缓存(TreeNode Cache)
为了加速文件的操作,每次更新flash上的索引树的速率较慢,所以在内存中建立树节点缓存以加快索引树查找。
垃圾回收
有一个空的LEB专门为垃圾回收保留。垃圾回收的一个例子如下:
首先选择一个脏LEB,比如LEB1被选中,然后将其有效数据拷贝的到LEB5,LEB1这时就可以被擦除了,然后再选择一个脏LEB区,如LEB6,同样将数据拷贝到LEB5,拷贝完成后LEB6上的原有数据可能被擦除掉,LEB1将未垃圾回收预留,LEB6这时处于可用状态。索引处理方法,只是将Tree Node Cache的索引节点标记为脏。这样垃圾回收完成。但是还进行一个确认操作,确认操作肯定是可以完成的,会为索引预留至少3倍的空闲空间。
图0.8 垃圾回收原理
LPT(LEB Properites Tree)
是一个B+树,但是大小固定,比主索引树小很多,管理方法类似于主索引树。
UBIFS初始化
UBIFS的文件系统需要编译的文件如下fs/ubifs/Makefile ,最后会编译成ubifs.o这个文件,链接时会将该文件链接到镜像文件中去。
Shrinker是动态调整树大小的。Journal是UBIFS的日志功能实现的文件,file、dir、super、sb以及io是文件、目录、超级块以及io操作实现;
Tnc(tree nodecache)模块,commit是在垃圾回收确认会用到的操作。gc是垃圾回收实现源码。
为了知道该模块的注册过程,首先查找相关的init函数。
透过上面的两个查找可以知道,UBIFS子系统在加载时会首先执行ubifs_init函数,这很late_initcall在《Linux系统启动那些事—基于Linux 3.10内核》一文提到过其调用的时机,在系统启动时会被调用。
[cpp] view plain copy
- Super.c
- static int __init ubifs_init(void)
- {
- 首先申请一个slab分配器,关于slab见《内存管理-之内核内存管理-基于linux3.10》
- ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab",
- sizeof(struct ubifs_inode), 0,
- SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT,
- &inode_slab_ctor);
- //将ubifs_shrinker(定义于shrinker.c文件)注册到VM子系统,在cache压力较大时,将会缩小TNC(tree node cache)。
- register_shrinker(&ubifs_shrinker_info);
- //UBIFS文件系统支持两种压缩格式lzo和zlib,该函数定义于compress.c文件,两种压缩格式在编译时根据宏选定。
- err = ubifs_compressors_init();
- //注册该文件系统,这个过程见《虚拟文件系统 (VFS)-基于linux3.10》,这里比较感兴趣的是ubifs_fs_type
- err = register_filesystem(&ubifs_fs_type);
- }
mount方法才是最感兴趣的,在《虚拟文件系统 (VFS)-基于linux3.10》里提到文件系统挂载时会调用具体的文件系统的mount方法,这里就来看看它的mount方法。
[cpp] view plain copy
- <super.c>
- static struct file_system_type ubifs_fs_type = {
- .name = "ubifs",
- .owner = THIS_MODULE,
- .mount = ubifs_mount,
- .kill_sb = kill_ubifs_super,
- };
Mount的函数虽然很重要,但是并没有想象中那么复杂,逻辑结构相对比较明晰。该函数首先调用open_ubi打开一个UBI设备,之所以以只读方式打开是因为这也许是一个新的挂载点,UBI同一时刻只允许有一个读写者。alloc_ubifs_info为描述UBIFS文件系统的结构体struct ubifs_info申请内存,并且初始化自旋锁、互斥锁、链表、树节点等操作。Sget首先在该文件系统中查找超级块,如果没有找到则调用alloc_super创建一个超级块,并初始化超级块的相关成员,该函数并未定义于ubifs文件目录内。然后调用ubifs_fill_super对超级块进行填充,填充的信息源于LEB0,这涉及到UBI和MTD层。由于fill_super()函数在一次打开了UBI,所以这里调用ubi_close_volume将其关闭。最后调用dget返回目录项。
图1.1 UBIFS挂载过程
假设挂载形式如《虚拟文件系统 (VFS)-基于linux3.10》提到的,如:
[cpp] view plain copy
- mount –t ubifs /dev/ubi4_0 /config
则open_ubi调用ubi_open_volume_path(“/dev/ubi4_0”,UBI_READONLY)查找UBI卷描述符。
[cpp] view plain copy
- struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
- {
- //该函数分析见《虚拟文件系统 (VFS)-基于linux3.10》
- error = kern_path(pathname, LOOKUP_FOLLOW, &path);
- inode = path.dentry->d_inode;
- mod = inode->i_mode;
- //获得主次设备号
- ubi_num = ubi_major2num(imajor(inode));
- vol_id = iminor(inode) - 1;
- path_put(&path);
- UBI卷描述符的获取
- if (vol_id >= 0 && ubi_num >= 0)
- return ubi_open_volume(ubi_num, vol_id, mode);
- }
ubi_open_volume获取UBI卷描述符,主要依赖前两个参数,第一个参数是UBI主设备号对应的数字,而第二个参数是UBI次设备号对应的数字。由主设备号索引到ubi设备,ubi_devices是一个局部全局的描述ubi设备的数组。
[cpp] view plain copy
- struct ubi_device *ubi;
- ubi = ubi_devices[ubi_num];
根据ubi设备信息找到UBI卷:
[cpp] view plain copy
- vol = ubi->volumes[vol_id];
alloc_ubifs_info主要功能就是slab分配内存,不多解释,有兴趣见《内存管理-之内核内存管理-基于linux3.10》。
sget用于查找并创建超级块
[cpp] view plain copy
- struct super_block *sget(struct file_system_type *type,
- int (*test)(struct super_block *,void *),
- int (*set)(struct super_block *,void *),
- int flags,
- void *data)
- {
- struct super_block *s = NULL;
- struct super_block *old;
- int err;
- retry:
- spin_lock(&sb_lock); //获得超级块锁
- //这个if语句就是在现有的文件系统中查找超级块是否存在
- if (test) { //这个函数在存在,实际上就是sb_test函数。
- hlist_for_each_entry(old, &type->fs_supers, s_instances) {
- if (!test(old, data))
- continue;
- if (!grab_super(old))
- goto retry;
- if (s) {
- up_write(&s->s_umount);
- destroy_super(s);
- s = NULL;
- }
- down_write(&old->s_umount);
- if (unlikely(!(old->s_flags & MS_BORN))) {
- deactivate_locked_super(old);
- goto retry;
- }
- return old;
- }
- }
- //如果s == null,则说明上面在ubifs文件系统中没有找到,则需要创建超级块,这里申请内存。
- if (!s) {
- spin_unlock(&sb_lock);
- s = alloc_super(type, flags);
- if (!s)
- return ERR_PTR(-ENOMEM);
- goto retry;
- }
- //调用set方法,为超级块设置一些内容。
- err = set(s, data);
- if (err) {
- spin_unlock(&sb_lock);
- up_write(&s->s_umount);
- destroy_super(s);
- return ERR_PTR(err);
- }
- //对超级块的一些其它字段的初始化。
- s->s_type = type;
- strlcpy(s->s_id, type->name, sizeof(s->s_id));
- list_add_tail(&s->s_list, &super_blocks);
- hlist_add_head(&s->s_instances, &type->fs_supers);
- spin_unlock(&sb_lock);
- get_filesystem(type);
- register_shrinker(&s->s_shrink);
- return s;
- }
如果sb->s_root为null,则说明还没挂载,该超级块的内容需要从flash上读取。这个任务有ubifs_fill_super实现。
该函数的原型如下:
[cpp] view plain copy
- static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
- sb参数是先前创建的超级块,首先将超级块描述ubifs信息的字段单独取出来
- struct ubifs_info *c = sb->s_fs_info;
- c->vfs_sb = sb;
- 这里重新打开改UBI设备,注意权限编程的读写,这意味着需要从该设备读写数据了。
- c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE);
- 初始化相关字段,bdi是backing_dev_info简写,其功能是禁止预读,不需要改功能。
- c->bdi.name = "ubifs",
- c->bdi.capabilities = BDI_CAP_MAP_COPY;
- err = bdi_init(&c->bdi);
- err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d",
- c->vi.ubi_num, c->vi.vol_id);
- err = ubifs_parse_options(c, data, 0);
- if (err)
- goto out_bdi;
- //超级块信息初始化
- sb->s_bdi = &c->bdi;
- sb->s_fs_info = c;
- sb->s_magic = UBIFS_SUPER_MAGIC;
- sb->s_blocksize = UBIFS_BLOCK_SIZE;
- sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT;
- sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c);
- if (c->max_inode_sz > MAX_LFS_FILESIZE)
- sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
- sb->s_op = &ubifs_super_operations;
- mutex_lock(&c->umount_mutex);
- //挂载ubifs文件系统。并调用ubifs_read_superblock读取超级块,使能日志功能等
- err = mount_ubifs(c);
- /*读取根索引节点*/
- root = ubifs_iget(sb, UBIFS_ROOT_INO);
- 将超级块和根索引节点关联
- sb->s_root = d_make_root(root);
UBIFS文件系统的读写实际上就是UBI层到MTD层的一个过程,其读代码的执行流程如下,
由于在这篇文章里并不分析UBI和MTD层,所以这里只列出散布在UBIFS文件目录里的各个函数接口,其功能和关键实现代码在后续文章中再剖析。
UBIFS接口函数集
Makefile中显示的各个编译后目标的文件提供的函数接口如下:
[cpp] view plain copy
- /* io.c */
- void ubifs_ro_mode(struct ubifs_info *c, int err);
- int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
- int len, int even_ebadmsg);
- int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
- int len);
- int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
- int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
- int ubifs_leb_map(struct ubifs_info *c, int lnum);
- int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
- int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
- int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs);
- int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
- int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
- int lnum, int offs);
- int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
- int lnum, int offs);
- int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
- int offs);
- int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
- int offs, int quiet, int must_chk_crc);
- void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
- void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last);
- int ubifs_io_init(struct ubifs_info *c);
- void ubifs_pad(const struct ubifs_info *c, void *buf, int pad);
- int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf);
- int ubifs_bg_wbufs_sync(struct ubifs_info *c);
- void ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum);
- int ubifs_sync_wbufs_by_inode(struct ubifs_info *c, struct inode *inode);
[cpp] view plain copy
- /* scan.c */
- struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
- int offs, void *sbuf, int quiet);
- void ubifs_scan_destroy(struct ubifs_scan_leb *sleb);
- int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
- int offs, int quiet);
- struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
- int offs, void *sbuf);
- void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
- int lnum, int offs);
- int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
- void *buf, int offs);
- void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
- void *buf);
[cpp] view plain copy
- /* log.c */
- void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud);
- void ubifs_create_buds_lists(struct ubifs_info *c);
- int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs);
- struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum);
- struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum);
- int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum);
- int ubifs_log_end_commit(struct ubifs_info *c, int new_ltail_lnum);
- int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum);
- int ubifs_consolidate_log(struct ubifs_info *c);
[cpp] view plain copy
- /* journal.c */
- int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
- const struct qstr *nm, const struct inode *inode,
- int deletion, int xent);
- int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
- const union ubifs_key *key, const void *buf, int len);
- int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode);
- int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode);
- int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
- const struct dentry *old_dentry,
- const struct inode *new_dir,
- const struct dentry *new_dentry, int sync);
- int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
- loff_t old_size, loff_t new_size);
- int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
- const struct inode *inode, const struct qstr *nm);
- int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode1,
- const struct inode *inode2);
[cpp] view plain copy
- /* budget.c */
- int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req);
- void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req);
- void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
- struct ubifs_inode *ui);
- int ubifs_budget_inode_op(struct ubifs_info *c, struct inode *inode,
- struct ubifs_budget_req *req);
- void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
- struct ubifs_budget_req *req);
- void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
- struct ubifs_budget_req *req);
- long long ubifs_get_free_space(struct ubifs_info *c);
- long long ubifs_get_free_space_nolock(struct ubifs_info *c);
- int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
- void ubifs_convert_page_budget(struct ubifs_info *c);
- long long ubifs_reported_space(const struct ubifs_info *c, long long free);
- long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs);
[cpp] view plain copy
- /* find.c */
- int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs,
- int squeeze);
- int ubifs_find_free_leb_for_idx(struct ubifs_info *c);
- int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
- int min_space, int pick_free);
- int ubifs_find_dirty_idx_leb(struct ubifs_info *c);
- int ubifs_save_dirty_idx_lnums(struct ubifs_info *c);
[cpp] view plain copy
- /* tnc.c */
- int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
- struct ubifs_znode **zn, int *n);
- int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
- void *node, const struct qstr *nm);
- int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
- void *node, int *lnum, int *offs);
- int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum,
- int offs, int len);
- int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key,
- int old_lnum, int old_offs, int lnum, int offs, int len);
- int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
- int lnum, int offs, int len, const struct qstr *nm);
- int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key);
- int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key,
- const struct qstr *nm);
- int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
- union ubifs_key *to_key);
- int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum);
- struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,
- union ubifs_key *key,
- const struct qstr *nm);
- void ubifs_tnc_close(struct ubifs_info *c);
- int ubifs_tnc_has_node(struct ubifs_info *c, union ubifs_key *key, int level,
- int lnum, int offs, int is_idx);
- int ubifs_dirty_idx_node(struct ubifs_info *c, union ubifs_key *key, int level,
- int lnum, int offs);
- /* Shared by tnc.c for tnc_commit.c */
- void destroy_old_idx(struct ubifs_info *c);
- int is_idx_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, int level,
- int lnum, int offs);
- int insert_old_idx_znode(struct ubifs_info *c, struct ubifs_znode *znode);
- int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu);
- int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu);
[cpp] view plain copy
- /* tnc_misc.c */
- struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
- struct ubifs_znode *znode);
- int ubifs_search_zbranch(const struct ubifs_info *c,
- const struct ubifs_znode *znode,
- const union ubifs_key *key, int *n);
- struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode);
- struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode);
- long ubifs_destroy_tnc_subtree(struct ubifs_znode *zr);
- struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
- struct ubifs_zbranch *zbr,
- struct ubifs_znode *parent, int iip);
- int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
- void *node);
[cpp] view plain copy
- /* tnc_commit.c */
- int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot);
- int ubifs_tnc_end_commit(struct ubifs_info *c);
- /* shrinker.c */
- int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc);
- /* commit.c */
- int ubifs_bg_thread(void *info);
- void ubifs_commit_required(struct ubifs_info *c);
- void ubifs_request_bg_commit(struct ubifs_info *c);
- int ubifs_run_commit(struct ubifs_info *c);
- void ubifs_recovery_commit(struct ubifs_info *c);
- int ubifs_gc_should_commit(struct ubifs_info *c);
- void ubifs_wait_for_commit(struct ubifs_info *c);
- /* master.c */
- int ubifs_read_master(struct ubifs_info *c);
- int ubifs_write_master(struct ubifs_info *c);
- /* sb.c */
- int ubifs_read_superblock(struct ubifs_info *c);
- struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c);
- int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup);
- int ubifs_fixup_free_space(struct ubifs_info *c);
- /* replay.c */
- int ubifs_validate_entry(struct ubifs_info *c,
- const struct ubifs_dent_node *dent);
- int ubifs_replay_journal(struct ubifs_info *c);
- /* gc.c */
- int ubifs_garbage_collect(struct ubifs_info *c, int anyway);
- int ubifs_gc_start_commit(struct ubifs_info *c);
- int ubifs_gc_end_commit(struct ubifs_info *c);
- void ubifs_destroy_idx_gc(struct ubifs_info *c);
- int ubifs_get_idx_gc_leb(struct ubifs_info *c);
- int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp);
- /* orphan.c */
- int ubifs_add_orphan(struct ubifs_info *c, ino_t inum);
- void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum);
- int ubifs_orphan_start_commit(struct ubifs_info *c);
- int ubifs_orphan_end_commit(struct ubifs_info *c);
- int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only);
- int ubifs_clear_orphans(struct ubifs_info *c);
[cpp] view plain copy
- /* lpt.c */
- int ubifs_calc_lpt_geom(struct ubifs_info *c);
- int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
- int *lpt_lebs, int *big_lpt);
- int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr);
- struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum);
- struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum);
- int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
- ubifs_lpt_scan_callback scan_cb, void *data);
- /* Shared by lpt.c for lpt_commit.c */
- void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave);
- void ubifs_pack_ltab(struct ubifs_info *c, void *buf,
- struct ubifs_lpt_lprops *ltab);
- void ubifs_pack_pnode(struct ubifs_info *c, void *buf,
- struct ubifs_pnode *pnode);
- void ubifs_pack_nnode(struct ubifs_info *c, void *buf,
- struct ubifs_nnode *nnode);
- struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c,
- struct ubifs_nnode *parent, int iip);
- struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c,
- struct ubifs_nnode *parent, int iip);
- int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip);
- void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty);
- void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode);
- uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits);
- struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght);
- /* Needed only in debugging code in lpt_commit.c */
- int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
- struct ubifs_nnode *nnode);
- /* lpt_commit.c */
- int ubifs_lpt_start_commit(struct ubifs_info *c);
- int ubifs_lpt_end_commit(struct ubifs_info *c);
- int ubifs_lpt_post_commit(struct ubifs_info *c);
- void ubifs_lpt_free(struct ubifs_info *c, int wr_only);
- /* lprops.c */
- const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
- const struct ubifs_lprops *lp,
- int free, int dirty, int flags,
- int idx_gc_cnt);
- void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst);
- void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
- int cat);
- void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops,
- struct ubifs_lprops *new_lprops);
- void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops);
- int ubifs_categorize_lprops(const struct ubifs_info *c,
- const struct ubifs_lprops *lprops);
- int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
- int flags_set, int flags_clean, int idx_gc_cnt);
- int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
- int flags_set, int flags_clean);
- int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp);
- const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c);
- const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c);
- const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c);
- const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c);
- int ubifs_calc_dark(const struct ubifs_info *c, int spc);
[cpp] view plain copy
- /* file.c */
- int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
- int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
- /* dir.c */
- struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
- umode_t mode);
- int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
- /* xattr.c */
- int ubifs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
- ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
- size_t size);
- ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size);
- int ubifs_removexattr(struct dentry *dentry, const char *name);
- /* super.c */
- struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);
- /* recovery.c */
- int ubifs_recover_master_node(struct ubifs_info *c);
- int ubifs_write_rcvrd_mst_node(struct ubifs_info *c);
- struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
- int offs, void *sbuf, int jhead);
- struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
- int offs, void *sbuf);
- int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf);
- int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf);
- int ubifs_rcvry_gc_commit(struct ubifs_info *c);
- int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
- int deletion, loff_t new_size);
- int ubifs_recover_size(struct ubifs_info *c);
- void ubifs_destroy_size_tree(struct ubifs_info *c);
- /* ioctl.c */
- long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
- void ubifs_set_inode_flags(struct inode *inode);
- #ifdef CONFIG_COMPAT
- long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
- #endif
- /* compressor.c */
- int __init ubifs_compressors_init(void);
- void ubifs_compressors_exit(void);
- void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
- int *compr_type);
- int ubifs_decompress(const void *buf, int len, void *out, int *out_len,
- int compr_type);
来源:CSDN
作者:dragon_cdut
链接:https://blog.csdn.net/renlonggg/article/details/103610509