Linux3.0.1移植YAFFS2 成功

Linux3.0.1Y移植 AFFS2成功 (2012-03-27 13:47)

转自:http://blog.chinaunix.net/uid-14114479-id-3150123.html 

YAFFS2移植Linux2.6.39.2 成功(需要更改YAFFS2官方最新源代码)附上自己修改好的Linux2.6.39.2-yaffs2.tar.gz。
原以为Linux内核的YAFFS2文件系统移植很简单,网上一大片的,多的是,其实只要给Linux内核打个补丁就行了,对于Linux2.6.37及以前的内核,可能真的是很简单,就像上面说的,直接下载YAFFS2源码,然后通过执行源代码内的补丁就行了,但是对于Linux2.6.38及以后的内核,估计打完补丁也会编译不过,因为Linux2.6.38是Linux内核发展的一个分水岭,FS文件系统发生了变化,据官方说还加入了一个啥子神奇补丁,没仔细研究过,不清楚,但是文件系统的确是发生了变化,正是这种文件系统的变化,导致了YAFFS2移植遇到了问题,好了,夜已深了,也搞了几个小时了,眼睛都快打架了,野棉花扯多了,呵呵,还是步入正题吧,喜欢与人分享我的经验,呵呵,菜鸟一个,经验估计也谈不上,还是算愚见吧!
好了,本来是打算写点OK6410之Linux2.6.39.2触摸屏等驱动移植愚见的,心血来潮,放在NAND第四分区(MTDBLOCK3)的QT-YAFFS2文件系统无法启动,心里就怪痒痒的,既然老天让我们在此时相遇,那我也不再躲闪了(原本是放在后面再移植的,因为原以为打个补丁就行了),哎,说真的,遇到编译不过时,在网上找了好久,完全找不到解决办法,哎,算了,还是自己慢慢分析,解决吧。
移植方法:
第一步,我们需要YAFFS2的源码,如果大家有兴趣想了解YAFFS2文件系统的驱动原理的话可以直接去访问他们的官网,地址是 www.yaffs.net,上面说的很详细的,也有源码下载地址,怕大家进去后难找,直接贴出YAFFS2的最新源码地址吧,2011年6月28号的那个版本,
免费下载地址在  http://linux.linuxidc.com/
用户名与密码都是 www.linuxidc.com
具体下载目录在 /pub/2011/06/28/YAFFS2/
这个是目前最新的YAFFS2的源码了,不过虽然是最新源码已经被打过好多次补丁,但是对于Linux2.6.39.2的内核版本,还是不给力啊,编译依然无法通过,不是说过了吗,文件系统发生了变化。
第二步,将下载下来的YAFFS2最新源码 YAFFS2.tar.gz 放入你Linux的任意一个目录下,执行 tar zxvf YAFFS2.tar.gz 然后进入YAFFS2源码包,由于最新的源码再执行脚本 patch-ker.sh 时 有四个参数,可以追加:c,l,m,s,
./patch-ker.sh  c/l m/s kernelpath
if c/l is c, then copy. If l then link
if m/s is m, then use multi version code. If s then use single version code
上面这段英文应该很好懂吧,简而言之,C 是复制文件,L是链接文件,M是多种,S是单个的,
那么在这里,我们只需执行 ./patch-ker.sh c m /your Linux2.6.39.2 kernel directory
执行完这条命令之后,你将会发现在Linux2.6.39.2/fs/下发现有了yaffs2目录了,并且里面也出现了好多文件
[email protected]:/SHARE/linux-2.6.39.2/fs/yaffs2# ls
Kconfig               yaffs_linux.h        yaffs_summary.c
Makefile              yaffs_mtdif1.c       yaffs_summary.h
yaffs_allocator.c     yaffs_mtdif1.h       yaffs_tagscompat.c
yaffs_allocator.h     yaffs_mtdif2.c       yaffs_tagscompat.h
yaffs_attribs.c       yaffs_mtdif2.h       yaffs_trace.h
yaffs_attribs.h       yaffs_mtdif.c        yaffs_verify.c
yaffs_bitmap.c        yaffs_mtdif.h        yaffs_verify.h
yaffs_bitmap.h        yaffs_nameval.c      yaffs_vfs.c
yaffs_checkptrw.c     yaffs_nameval.h      yaffs_yaffs1.c
yaffs_checkptrw.h     yaffs_nand.c         yaffs_yaffs1.h
yaffs_ecc.c           yaffs_nand.h         yaffs_yaffs2.c
yaffs_ecc.h           yaffs_packedtags1.c  yaffs_yaffs2.h
yaffs_getblockinfo.h  yaffs_packedtags1.h  yportenv.h
yaffs_guts.c          yaffs_packedtags2.c
yaffs_guts.h          yaffs_packedtags2.h
说明这个补丁是打成功了,同时,你会发现,在fs目录下的Kconfig 和Makefile文件里也被相应的添加了加入yaffs2的支持信息,好了,到这一步,说明YAFFS2的补丁是打上了,但是由于是新版的LINUX2.6.39.2,所以导致编译无法通过,如果你不信的话,可以现在就编译试试看,会在生成YAFFS2.o时出错,而错误主要就是出现 在yaffs_vfs.c
这个文件上,
一个是
.get_sb ERROR问题,
还有就是get_sb_bdev ERROR问题。
根据自己的仔细分析,原来是新版的LINUX2.6.39.2文件系统发生变化,通过代码定位,
在LINUX2.6.39.2/includde/linux/fs.h上发现了一丝端倪,原来在新版的linux2.6.39.2里面,由于VFS发生变化,对于get_sb 以及get_sb_bdev这两个变量均为使用,
struct file_system_type {
 const char *name;

 
 int fs_flags;
 struct dentry *(*mount) (struct file_system_type *, int,
         const char *, void *);
 void (*kill_sb) (struct super_block *);
      。。。。。。
     },在file_system_type这个结构体中我们根本就找不到  get_sb这个变量
通过对比linux2.6.36内核里面的fs.h,
struct file_system_type {
 const char *name;
 int fs_flags;
 int (*get_sb) (struct file_system_type *, int,
         const char *, void *, struct vfsmount *);
 void (*kill_sb) (struct super_block *);
 struct module *owner;
............
  }
发现在结构体file_system_type是有get_sb这个变量定义的,
而在yaffs_vfs.c里面有两处是需要这个变量的,
第一处:
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,
};  所以,我们需要更改yaffs_vfs.c里面的get_sb这个变量满足LINUX2.6.39.2的要求,通过比对,不难发现,其实LINUX2.6.39.2的fs.h里面的
struct dentry *(*mount) (struct file_system_type *, int,
         const char *, void *);这个函数与
int (*get_sb) (struct file_system_type *, int,
         const char *, void *, struct vfsmount *);很相似,
于是 直接修改yaffs_vfs.c的
      static struct file_system_type yaffs_fs_type
以及static struct file_system_type yaffs2_fs_type
两个结构体的get_sb变量,分别为:
.mount = yaffs_read_super,
.mount = yaffs2_read_super, 同理,对比,发现,用mount_bdev函数变量代替get_sb_bdev函数变量
return mount_bdev(fs, flags, dev_name, data,
      yaffs_internal_read_super_mtd);
return mount_bdev(fs, flags, dev_name, data,
      yaffs2_internal_read_super_mtd);
第三步:
 
由于mount这个结构体函数少了struct vfsmount 这个参数,因此,我们还需要更改yaffs_vfs.c的两个位置,
通过阅读源代码不难发现
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
      int silent)
{
 return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
}
/*
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs_read_super(struct file_system_type *fs,
       int flags, const char *dev_name,
       void *data, struct vfsmount *mnt)
{
 return get_sb_bdev(fs, flags, dev_name, data,
      yaffs_internal_read_super_mtd, mnt);
}
#else
static struct super_block *yaffs_read_super(struct file_system_type *fs,
         int flags, const char *dev_name,
         void *data)
{
 return get_sb_bdev(fs, flags, dev_name, data,
      yaffs_internal_read_super_mtd);
}
#endif
*/
 
static struct super_block *yaffs_read_super(struct file_system_type *fs,
         int flags, const char *dev_name,
         void *data)
{
  return mount_bdev(fs, flags, dev_name, data,
      yaffs_internal_read_super_mtd);
}
static struct file_system_type yaffs_fs_type = {
 .owner = THIS_MODULE,
 .name = "yaffs",
  //.get_sb = yaffs_read_super,
 .mount = yaffs_read_super,
 .kill_sb = kill_block_super,
 .fs_flags = FS_REQUIRES_DEV,
};
#else
static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
         int silent)
{
 return yaffs_internal_read_super(1, sb, data, silent);
}
static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
        FS_REQUIRES_DEV);
#endif

在这段代码中,我发现,当LINXU内核版本大于2.6.17时与大于2.5.0而小于2.6.17时,采用的yaffs_read_super函数不一样,参数个数不同,而且类型也有所不同,一个是整形,一个是结构体,于是修改代码,红色为删掉不要的,蓝色为更改的,同理,第二处YAFFS2修改方法原理同上:直接贴出
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
       int silent)
{
 return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
}
/*
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs2_read_super(struct file_system_type *fs,
        int flags, const char *dev_name, void *data,
        struct vfsmount *mnt)
{
 return get_sb_bdev(fs, flags, dev_name, data,
      yaffs2_internal_read_super_mtd, mnt);
}
#else
static struct super_block *yaffs2_read_super(struct file_system_type *fs,
          int flags, const char *dev_name,
          void *data)
{
 return get_sb_bdev(fs, flags, dev_name, data,
      yaffs2_internal_read_super_mtd);
}
#endif
*/
static struct super_block *yaffs2_read_super(struct file_system_type *fs,
          int flags, const char *dev_name,
          void *data)
{
 return mount_bdev(fs, flags, dev_name, data,
      yaffs2_internal_read_super_mtd);
}
static struct file_system_type yaffs2_fs_type = {
 .owner = THIS_MODULE,
 .name = "yaffs2",
 //.get_sb = yaffs2_read_super,
 .mount = yaffs2_read_super,
 .kill_sb = kill_block_super,
 .fs_flags = FS_REQUIRES_DEV,
};
#else
static struct super_block *yaffs2_read_super(struct super_block *sb,
          void *data, int silent)
{
 return yaffs_internal_read_super(2, sb, data, silent);
}
static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
        FS_REQUIRES_DEV);
#endif     好了,经过这3步修改之后,编译通过,当然,还是会有告警信息打印,很正常,因为原来的get_sb_bdev函数是一个 INT型,而mount_bdev函数是一个 STRUCT结构体型,导致RETURN 指针类型不符的告警,无大碍。
 

运行很好,完全没问题,通过[root@FORLINX6410 /]# cat /proc/filesystems   打印信息:
nodev   sockfs
nodev   usbfs
nodev   pipefs

 
nodev   anon_inodefs
nodev   rpc_pipefs
nodev   devpts
        ext3
        ext2
        cramfs
nodev   ramfs
        vfat
        msdos
nodev   nfs
nodev   nfs4
nodev   nfsd
        ntfs
        romfs
nodev   fuse
        fuseblk
nodev   fusectl
        yaffs
        yaffs2
nodev   mtd_inodefs
可见,这个修改方法还是很成功的 ,看到网上那么多的朋友都遇到LINUX2.6.38及以后版本的YAFFS2的文件系统移植问题,又没人提出解决方案,所以一解决问题就马上贴了出来,希望对你们有所帮助!!好了,该睡觉了啊,写的有点仓促,如果有地方没看明白,就留言吧。
最后还是附上我修改好的LINUX2.6.39.2的YAFFS2的包包吧,
免费下载地址在  http://linux.linuxidc.com/
用户名与密码都是 www.linuxidc.com
具体下载目录在 /pub/2011/06/28/YAFFS2/修改好的Linux2.6.39.2的YAFFS2的包
安装方法,在linux2.6.39.2/fs/ 下 mkdir yaffs2 然后解压,将其全部内容拷贝进去,并修改linux2.6.39.2/fs/ 下的Kconfig 在
source "fs/efs/Kconfig"与
source "fs/jffs2/Kconfig"之间添加source "fs/yaffs2/Kconfig",然后还需修改Makefile,在最后一行添加:
obj-$(CONFIG_YAFFS_FS)  += yaffs2/,最后贴上我的MENUCONFIG吧:
   <*>   yaffs2 file system support                                  
     -*-     512 byte / page devices 
     -*-     2048 byte (or larger) / page devices                     
    [*]       Autoselect yaffs2 format 
    [*]     Enable yaffs2 xattr support


你可能感兴趣的:(Linux3.0.1移植YAFFS2 成功)