今天发现sqashfs制作的根文件系统不需要像jffs2那样需要增加内核命令行:rootfstype=jffs2。看了一下内核挂载根文件系统个过程,发现是JFFS2注册文件系统时少设置了一个标志:FS_REQUIRES_DEV。
修改点: fs/jffs2/super.c
static struct file_system_type jffs2_fs_type = {
.owner = THIS_MODULE,
.name = "jffs2",
.get_sb = jffs2_get_sb,
.kill_sb = jffs2_kill_sb,
.fs_flags = FS_REQUIRES_DEV,
};
有了这个标志表示该文件系统不是虚文件系统,必须要有实际的块设备。(参考: http://www.win.tue.nl/~aeb/linux/lk/lk-8.html)
通过cat /proc/filesystems, 如果没有'nodev'这个字符串,就说明带了这个标志。
$ cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
nodev proc
nodev sockfs
nodev pipefs
nodev futexfs
nodev tmpfs
nodev eventpollfs
nodev devpts
squashfs
nodev ramfs
jffs2
nodev autofs
nodev mqueue
内核在挂载根文件系统时,如果没有命令行参数指定根文件系统类型,会从注册的所有文件系统中挑选有这个标志的文件系统一一尝试。
代码如下:
void __init mount_block_root(char *name, int flags)
{
char *fs_names = __getname();
char *p;
char b[BDEVNAME_SIZE];
get_fs_names(fs_names);
retry:
for (p = fs_names; *p; p += strlen(p)+1) {
int err = do_mount_root(name, p, flags, root_mount_data);
switch (err) {
case 0:
goto out;
case -EACCES:
flags |= MS_RDONLY;
goto retry;
case -EINVAL:
continue;
}
/*
* Allow the user to distinguish between failed sys_open
* and bad superblock on root device.
*/
__bdevname(ROOT_DEV, b);
printk("VFS: Cannot open root device \"%s\" or %s\n",
root_device_name, b);
printk("Please append a correct \"root=\" boot option\n");
panic("VFS: Unable to mount root fs on %s", b);
}
panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b));
out:
putname(fs_names);
}
static void __init get_fs_names(char *page)
{
char *s = page;
if (root_fs_names) {
strcpy(page, root_fs_names);
while (*s++) {
if (s[-1] == ',')
s[-1] = '\0';
}
} else {
int len = get_filesystem_list(page);
char *p, *next;
page[len] = '\0';
for (p = page-1; p; p = next) {
next = strchr(++p, '\n');
if (*p++ != '\t') /* no 'nodev' in the string */
continue;
while ((*s++ = *p++) != '\n')
;
s[-1] = '\0';
}
}
*s = '\0';
}