UBI文件系统分析
struct ubi_device *ubi; int i, err, do_free = 1;
/* * Check if we already have the same MTD device attached. * * Note, this function assumes that UBI devices creations and deletions * are serialized, so it does not take the &ubi_devices_lock. */ for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi->vid_hdr_offset = vid_hdr_offset; ubi->autoresize_vol_id = -1;
mutex_init(&ubi->buf_mutex); mutex_init(&ubi->ckvol_mutex); mutex_init(&ubi->mult_mutex); mutex_init(&ubi->volumes_mutex); spin_lock_init(&ubi->volumes_lock); 初始化信号 ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
int err; struct ubi_scan_info *si;
si = ubi_scan(ubi); ********************************************************************* ************* 这儿通过 ubi_scan 函数来扫描 MTD 分区的每一块。具体是调用 static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,int pnum) 函数来读取 EC 和 VID 头(即没一块的前两页),在读每一页的时候,会调用 check_pattern 函数来判断这一页是否为空,如果每一页都是空的,那么就会 发现这个 MTD 分区是空的。 ********************************************************************* *************
if (mtd->type == MTD_UBIVOLUME) { ubi_err("refuse attaching mtd%d - it is already emulated on " "top of UBI", mtd->index); return -EINVAL;
} 上面的代码接着检查被 attach 的 mtd 设备时候是一个 mtd volume(卷区), 如果已经是一个 mtd 卷了,那么就不能再被 attach 了。
ubi = ubi_devices[i]; if (ubi && mtd->index == ubi->mtd->index) {
dbg_err("mtd%d is already attached to ubi%d", mtd->index, i);
return -EEXIST; } } //上面的这段代码可以看英文注释,一个 mtd 设备(一个分区)不能被 attach 两次,除非你已经 deatch 了。所以在这段代码的开始就检查被 attach 的 mtd 设备是否已经被 attach 了。
~(ubi->hdrs_min_io_size - 1);
ubi->vid_hdr_shift = ubi->vid_hdr_offset -
ubi->vid_hdr_aloffset;
}
Io_init 剩余的部分就不分析了,比较容易
接着上面 ubi_attach_mtd_dev()往下说:
ubi->peb_buf1 = vmalloc(ubi->peb_size);
ubi_err("min. I/O unit (%d) is not power of 2", ubi->min_io_size);
return -EINVAL; }
ubi_assert(ubi->hdrs_min_io_size > 0); ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size); ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);
如果在终端输入命令的时候没有带 ubinum,那么就是自动分配 ubinum,系统就 会从 ubi_device[]数组中找出一个没被使用的 ubinum 号
if (ubi_num == UBI_MAX_DEVICES) { dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES); return -ENFILE;
if (!ubi->peb_buf1)
goto out_free;
ubi->peb_buf2 = vmalloc(ubi->peb_size); if (!ubi->peb_buf2)
goto out_free; 分配两个物理擦除块大小的 buf,具体的用途下面再说
err = attach_by_scanning(ubi); if (err) {
} } else {
if (ubi_num >= UBI_MAX_DEVICES) return -EINVAL;
如果 ubi_num > UBI_MAX_DEVICES,就代表没有空余 ubinum 号可供分配,返回 出错
/* Make sure ubi_num is not busy */ if (ubi_devices[ubi_num]) {
if (ubi_num == UBI_DEV_NUM_AUTO) { /* Search for an empty slot in the @ubi_devices array */ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) if (!ubi_devices[ubi_num]) break;
} Numeraseregions 是扫描 nandflash 得到的信息,如果 numeraseregions 等于 0,代表我们需要 attach 的设备已经擦除过了
if (ubi->vid_hdr_offset < 0) return -EINVAL;
ubi->vid_hdr_offset 显然应该是一个正数,一般是 nandflash 的一页,我们 的 4020 上的 nandflash 页大小为 512 字节,所以 ubi->vid_hdr_offset 为 512. 这儿再稍微说一下,EC header 和 VID header,是记录我们 ubi 管理信息。一 般 EC 在一个擦除块的第一页,所以偏移量为 0,VID 在擦除块的第二页上,所 以偏移量为 512.,在我们 4020 的 nandflash 上,一个擦除块的大小为 16K,也 就是 32 页。 下面接着讲我们的扫描信息写进 mtd 结构体
dbg_err("failed to attach by scanning, error %d", err); goto out_free; }
我们再跟着 attach_by_scanning(ubi)细说 static int attach_by_scanning(struct ubi_device *ubi) {
UBIFS文件系统分析(一):挂载UBIFS的
代码分析
陆陆续续的看 UBIFS 很长时间了,一直没有写出一点东西。因为我在=到能够系 统的理解 UBIFS 的时候再写出一点东西。但是因为工作比较忙,UBIFS 源码读 的断断续续,老是需要复习拾起,比较浪费时间,所以决定写出一点东西,做 个备份吧。 我决定在读 UBIFS 源码之前需要读两份关于 UBIF 设计的文档: 一份是《UBI-Unsorted Block Images》 ubidesign.pdf 另外一份是《A Brief Introduction to the design of UBIFS》 A Brief Introduction to the Design of UBIFS.pdf 这两份简洁的介绍了 UBIFS 设计的一些结构和考虑。 我们按照挂载 ubifs 的工序来分析代码: (1)ubiattach /dev/ubi_ctrl -m 3 (2)ubimkvol /dev/ubi0 -N ubifs -s 15MiB (3)mount -t ubifs ubi0:ubifs /mnt 首先先分析(1),相应的代码是 ubi_attach_mtd_dev()函数,下面我们紧 跟代码来看看究竟干了些什么。 1.ubi_attach_mtd_dev int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) { //ubi_num, vid_hdr_offset 是命令传进来的参数
if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) ubi->bad_allowed = 1;
ubi->min_io_size = ubi->mtd->writesize; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd>subpage_sft; if (!is_power_of_2(ubi->min_io_size)) {