`

浅析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]

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics