浅析yaffs2文件系统被mount的梗概流程

浅析yaffs2文件系统被mount的梗概流程

浅析linux下mtd设备onenand存储器的分区和节点创建流程及yaffs2文件系统挂载

在init.rc脚本中
on init

loglevel 3
    ...
    mkdir /system
    mkdir /local 0777 system system
    mkdir /data 0771 system system
# mount mtd partitions
    # Mount /system rw first to give the filesystem a chance to save a checkpoint
    mount yaffs2 mtd@system /system

    # We chown/chmod /data again so because mount is run as root + defaults
    mount yaffs2 mtd@userdata /data
    chown system system /data
    chmod 0771 /data

    # Same reason as /data above
    mount yaffs2 mtd@local /local
    chown system system /local
    chmod 0777 /local
    ...
所以init进程将在执行init.rc脚本时,会执行mtd文件系统的mount操作,
比如:mount yaffs2 mtd@system /system
int do_mount(int nargs, char **args)
{
    ...
    source = args[2];
    if (!strncmp(source, "mtd@", 4)) {
        n = mtd_name_to_number(source + 4);//进行转换
        if (n >= 0) {
            sprintf(tmp, "/dev/block/mtdblock%d", n);
            source = tmp;
        }
    }
    return mount(source, args[3], args[1], flags, options);
    //source 为"/dev/block/mtdblock0等"
    //args[3] 为"/system"
    //args[2] 为"yaffs2"这是文件系统的名字,即:init_yaffs_fs注册登记的如下yaffs系统
    //
    //static struct file_system_to_install fs_to_install[] = {
    //#ifdef CONFIG_YAFFS_YAFFS1
    //{&yaffs_fs_type, 0},
    //#endif
    //#ifdef CONFIG_YAFFS_YAFFS2
    //{&yaffs2_fs_type, 0},
    //#endif
    //{NULL, 0}
};
static struct file_system_type yaffs_fs_type = {
    .owner = THIS_MODULE,
    .name = "yaffs",
    .get_sb = yaffs_read_super,
    .kill_sb = kill_block_super,
    .fs_flags = FS_REQUIRES_DEV,
};
static struct file_system_type yaffs2_fs_type = {
    .owner = THIS_MODULE,
    .name = "yaffs2",
    .get_sb = yaffs2_read_super,
    .kill_sb = kill_block_super,
    .fs_flags = FS_REQUIRES_DEV,
};

    //来看看系统调用sys_mount[luther.gliethttp]
    asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name,
             char __user * type, unsigned long flags,
             void __user * data)
}

int mtd_name_to_number(const char *name)
{
    int n;
    if (mtd_part_count < 0) {
        mtd_part_count = 0;
        find_mtd_partitions();
    }
    for (n = 0; n < mtd_part_count; n++) {
        if (!strcmp(name, mtd_part_map[n].name)) {
            return mtd_part_map[n].number;
        }
    }
    return -1;
}

static void find_mtd_partitions(void)
{
    int fd;
    char buf[1024];
    char *pmtdbufp;
    ssize_t pmtdsize;
    int r;

    fd = open("/proc/mtd", O_RDONLY);
    if (fd < 0)
        return;

    buf[sizeof(buf) - 1] = '/0';
    pmtdsize = read(fd, buf, sizeof(buf) - 1);
    pmtdbufp = buf;
    while (pmtdsize > 0) {
        int mtdnum, mtdsize, mtderasesize;
        char mtdname[16];
        mtdname[0] = '/0';
        mtdnum = -1;
        r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
                   &mtdnum, &mtdsize, &mtderasesize, mtdname);
        if ((r == 4) && (mtdname[0] == '"')) {
            char *x = strchr(mtdname + 1, '"');
            if (x) {
                *x = 0;
            }
            INFO("mtd partition %d, %s/n", mtdnum, mtdname + 1);
            if (mtd_part_count < MAX_MTD_PARTITIONS) {
                strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
                mtd_part_map[mtd_part_count].number = mtdnum;
                mtd_part_count++;
            } else {
                ERROR("too many mtd partitions/n");
            }
        }
        while (pmtdsize > 0 && *pmtdbufp != '/n') {
            pmtdbufp++;
            pmtdsize--;
        }
        if (pmtdsize > 0) {
            pmtdbufp++;
            pmtdsize--;
        }
    }
    close(fd);
}


# cat /proc/mtd,这里由init_yaffs_fs驱动完成
dev: size erasesize name
mtd0: 00100000 00020000 "Bootloader"
mtd2: 000c0000 00020000 "NVM"
mtd3: 00040000 00020000 "logo"
mtd4: 00300000 00020000 "Kernel"
mtd5: 06000000 00020000 "system"
mtd7: 04000000 00020000 "userdata"
mtd8: 01e00000 00020000 "local"
mtd9: 008c0000 00020000 "cache"
mtd10: 00600000 00020000 "fota"
mtd11: 00080000 00020000 "panic"
mtd12: 00080000 00020000 "BBT"


至于"/dev/block/mtdblock%d"下面的这些节点是在什么时候,由谁创建的,
分为2部分,一部分是平台提供的flash分配图,如下:
在arch/arm/mach-pxa/luther.c这个产品平台文件中,即:
MACHINE_START(LUTHER, "luther")
    .phys_io = 0x40000000,
    .boot_params = 0xa0000100,
    .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
    .map_io = pxa_map_io,
    .init_irq = pxa3xx_init_irq,
    .timer = &pxa_timer,
    .init_machine = luther_init,
MACHINE_END

static struct mtd_partition android_256m_v75_partitions[] = {
    [0] = {
        .name = "Bootloader",
        .offset = 0,
        .size = 0x100000,
        .mask_flags = MTD_WRITEABLE, /* force read-only */
    },
    ...
    [3] = {
        .name = "logo",
        .offset = 0xa00000,
        .size = 0x040000,
        .mask_flags = MTD_WRITEABLE, /* force read-only */
    },
    [4] = {
        .name = "Kernel",
        .offset = 0xa40000,
        .size = 0x300000,
        .mask_flags = MTD_WRITEABLE, /* force read-only */
    },
    [5] = {
        .name = "system",
        .offset = 0x0d40000,
        .size = 0x6000000, /* mount 96M fs */
    },
    ...
};

static void __init _init_onenand(void)
{
    if (is_android()) {
        luther_onenand_info.parts = android_256m_v75_partitions;
        luther_onenand_info.nr_parts =
            ARRAY_SIZE(android_256m_v75_partitions);
    }
    else {
        luther_onenand_info.parts = pxa930_256m_v75_partitions;
        luther_onenand_info.nr_parts =
            ARRAY_SIZE(pxa930_256m_v75_partitions);
    }

    pxa3xx_device_onenand.dev.platform_data = &luther_onenand_info;
    platform_device_register(&pxa3xx_device_onenand);
}
令一部分就是对应的驱动:
drivers/mtd/onenand/generic.c
#define DRIVER_NAME    "onenand"
static struct platform_driver generic_onenand_driver = {
    .driver = {
        .name    = DRIVER_NAME,
    },
    .probe        = generic_onenand_probe,
    .remove        = generic_onenand_remove,
#ifdef CONFIG_PM
    .suspend    = NULL,
    .resume        = NULL,
#endif
};
所以最后调用probe函数来创建平台文件luther.c中指定的flash配置图,
static int __devinit generic_onenand_probe(struct platform_device *dev)
{
    struct onenand_info *info;
    struct platform_device *pdev = dev;
    struct flash_platform_data *pdata = pdev->dev.platform_data;
    struct resource *res = pdev->resource;
    unsigned long size = res->end - res->start + 1;
    int err;

    info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
    if (!info)
        return -ENOMEM;

    if (!request_mem_region(res->start, size, pdev->name)) {
        err = -EBUSY;
        goto out_free_info;
    }

    info->onenand.base = ioremap(res->start, size);
    if (!info->onenand.base) {
        err = -ENOMEM;
        goto out_release_mem_region;
    }

    info->onenand.mmcontrol = pdata->mmcontrol;
    info->onenand.irq = platform_get_irq(pdev, 0);

    info->mtd.name = pdev->dev.bus_id;
    info->mtd.priv = &info->onenand;
    info->mtd.owner = THIS_MODULE;

    if (onenand_scan(&info->mtd, 1)) {
        err = -ENXIO;
        goto out_iounmap;
    }

#ifdef CONFIG_MTD_PARTITIONS
    err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
    if (err > 0)
        add_mtd_partitions(&info->mtd, info->parts, err);
    else if (err < 0 && pdata->parts)
        add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);//添加设备创建设备节点
    else
#endif
        err = add_mtd_device(&info->mtd);

    dev_set_drvdata(&pdev->dev, info);

    return 0;

out_iounmap:
    iounmap(info->onenand.base);
out_release_mem_region:
    release_mem_region(res->start, size);
out_free_info:
    kfree(info);

    return err;
}
以上是一个大体的流程梗概,对于更细致的分析,以后有时间再慢慢解读[luther.gliethttp]

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值