Linux开发十七_yaffs文件系统

Linux开发十七

yaffs文件系统

象棋小子    1048272975

nand flash作为市面上最主要的非易失性闪存技术之一,应用在各种固态大容量存储解决方案中。由于nand flash自身的特点,nand存储器往往需要一款专用的nand文件系统进行管理。开源的yaffs文件系统由于其优异的性能,在nand flash中受到广泛的应用。

1. yaffs文件系统

从yaffs官网下载最新的yaffs源码,进入到yaffs目录,给Linux内核加上yaffs文件系统补丁。

./patch-ker.sh c m /usr/linux-4.10.10

由于yaffs滞后于Linux内核以及自身更新的不同步,编译yaffs将会产生较多的错误。此处根据linux-4.10.10内核编译错误进行更改,大部分是更改yaffs与Linux内核的接口文件yaffs_vfs.c。

1.1.  编译归类一

fs/yaffs2/yaffs_vfs.c:423:13: error: 'PAGE_CACHE_SIZE'undeclared (first use in this function)

  n_bytes = PAGE_CACHE_SIZE;

             ^

fs/yaffs2/yaffs_vfs.c: In function'yaffs_write_begin':

fs/yaffs2/yaffs_vfs.c:525:25: error:'PAGE_CACHE_SHIFT' undeclared (first use in this function)

  pgoff_t index = pos >> PAGE_CACHE_SHIFT;

                         ^

fs/yaffs2/yaffs_vfs.c:574:3: error:implicit declaration of function 'page_cache_release'[-Werror=implicit-function-declaration]

  page_cache_release(pg);

内核不再在中定义PAGE_CACHE_SHIFT、PAGE_CACHE_SIZE、page_cache_release,在yaffs_vfs.c中加入宏定义。

+#define PAGE_CACHE_SHIFT         PAGE_SHIFT

+#define PAGE_CACHE_SIZE           PAGE_SIZE

+#define page_cache_release(page)       put_page(page)

1.2. 编译归类二

fs/yaffs2/yaffs_vfs.c: In function'yaffs_readpage_nolock':

fs/yaffs2/yaffs_vfs.c:294:29: error:'struct file' has no member named 'f_dentry'

 obj = yaffs_dentry_to_obj(f->f_dentry);

内核struct file结构体的更改,在yaffs_vfs.c中更改f_dentry的定义。

+#define f_dentry f_path.dentry

1.3. 编译归类三

fs/yaffs2/yaffs_vfs.c: At top level:

fs/yaffs2/yaffs_vfs.c:789:10: error:'new_sync_read' undeclared here (not in a f

unction)

 .read = new_sync_read,

 

fs/yaffs2/yaffs_vfs.c:790:11: error:'new_sync_write' undeclared here (not in a

function)

 .write = new_sync_write,

内核不再有new_sync_read、new_sync_write接口,不再需要file_operations的.read、.write接口,同样注释yaffs_file_operations的.read,.write接口。

-      .read= new_sync_read,

-      .write= new_sync_write,

1.4. 编译归类四

fs/yaffs2/yaffs_vfs.c: At top level:

fs/yaffs2/yaffs_vfs.c:1047:2: error:unknown field 'setxattr' specified in initializer

 .setxattr = yaffs_setxattr,

 ^

fs/yaffs2/yaffs_vfs.c:1047:2: warning:initialization from incompatible pointer type [enabled by default]

fs/yaffs2/yaffs_vfs.c:1047:2: warning:(near initialization for 'yaffs_file_inode_operations.getattr') [enabled bydefault]

fs/yaffs2/yaffs_vfs.c:1048:2: error:unknown field 'getxattr' specified in initializer

 .getxattr = yaffs_getxattr,

 ^

fs/yaffs2/yaffs_vfs.c:1048:2: warning:initialization from incompatible pointer type [enabled by default]

fs/yaffs2/yaffs_vfs.c:1048:2: warning:(near initialization for 'yaffs_file_inode_operations.listxattr') [enabled bydefault]

fs/yaffs2/yaffs_vfs.c:1050:2: error:unknown field 'removexattr' specified in initializer

 .removexattr = yaffs_removexattr,

内核struct inode_operations结构体移除了.setxattr、.getxattr、.removexattr接口,注释掉.setxattr、 .getxattr、 .removexattr,更改yaffs使用通用的xattr处理,并更改yaffs_setxattr、yaffs_getxattr的接口定义。

-static int yaffs_setxattr(struct dentry*dentry, const char *name,

+

+static int yaffs_setxattr(struct dentry*dentry, struct inode *node, const char *name, 

               const void *value, size_t size, int flags)

 {

      struct inode *inode = dentry->d_inode;

@@ -941,8 +948,9 @@

      return error;

 }

 

-static ssize_t yaffs_getxattr(structdentry * dentry, const char *name,

-                    void*buff, size_t size)

+

+static ssize_t yaffs_getxattr(structdentry * dentry, struct inode *node,

+                                 constchar *name, void *buff, size_t size)

 {

      struct inode *inode = dentry->d_inode;

      int error = 0;

@@ -1016,13 +1024,39 @@

      return error;

 }

 

+static int yaffs_xattr_get(const structxattr_handler *handler,

+                          structdentry *dentry, struct inode *inode,

+                          constchar *name, void *buff, size_t size)

+{

+     returnyaffs_getxattr(dentry, inode, name, buff, size);

+}

+

+static int yaffs_xattr_set(const structxattr_handler *handler,

+                          structdentry *dentry, struct inode *inode,

+                          constchar *name, const void *value, size_t size,

+                          intflags)

+{

+     if(value)

+            returnyaffs_setxattr(dentry, inode, name, value, size, flags);

+     else

+            returnyaffs_removexattr(dentry, name);

+}

+

+static const struct xattr_handleryaffs_xattr_handler = {

+     .prefix= "", /* match anything */

+     .get= yaffs_xattr_get,

+     .set= yaffs_xattr_set,

+};

+

+static const struct xattr_handler*yaffs_xattr_handlers[] = {

+     &yaffs_xattr_handler,

+     NULL

+};

+

 

 static const struct inode_operationsyaffs_file_inode_operations = {

      .setattr = yaffs_setattr,

-      .setxattr= yaffs_setxattr,

-      .getxattr= yaffs_getxattr,

      .listxattr = yaffs_listxattr,

-      .removexattr= yaffs_removexattr,

 };

 

/*-----------------------------------------------------------------*/

@@ -2783,6 +2796,7 @@

 

      sb->s_magic = YAFFS_MAGIC;

      sb->s_op = &yaffs_super_ops;

+     sb->s_xattr= yaffs_xattr_handlers;

      sb->s_flags |= MS_NOATIME;

1.5. 编译归类五

fs/yaffs2/yaffs_vfs.c: In function'yaffs_setattr':

fs/yaffs2/yaffs_vfs.c:898:3: error:implicit declaration of function 'inode_change_ok'[-Werror=implicit-function-declaration]

  error = inode_change_ok(inode, attr);

内核用setattr_prepare()替代inode_change_ok()。

-             error= inode_change_ok(inode, attr);

+            error= setattr_prepare(dentry, attr);

1.6. 编译归类六

fs/yaffs2/yaffs_vfs.c:1050:2: warning:initialization from incompatible pointer type [enabled by default]

fs/yaffs2/yaffs_vfs.c:1050:2: warning:(near initialization for 'yaffs_file_inode_operations.fiemap') [enabled bydefault]

fs/yaffs2/yaffs_vfs.c: In function'yaffs_follow_link':

fs/yaffs2/yaffs_vfs.c:1103:2: error:implicit declaration of function 'nd_set_link' [-Werror=implicit-function-declaration]

 nd_set_link(nd, alias);

 ^

fs/yaffs2/yaffs_vfs.c: At top level:

fs/yaffs2/yaffs_vfs.c:1143:2: error:unknown field 'follow_link' specified in initializer

 .follow_link = yaffs_follow_link,

 ^

fs/yaffs2/yaffs_vfs.c:1143:2: warning:initialization from incompatible pointer type [enabled by default]

fs/yaffs2/yaffs_vfs.c:1143:2: warning:(near initialization for 'yaffs_symlink_inode_operations.create') [enabled bydefault]

fs/yaffs2/yaffs_vfs.c:1145:2: error:unknown field 'put_link' specified in initializer

 .put_link = yaffs_put_link,

struct inode_operations结构体中,内核用.get_link替代.follow_link/.put_link。

-#if (YAFFS_NEW_FOLLOW_LINK == 1)

-static void *yaffs_follow_link(structdentry *dentry, struct nameidata *nd)

+static const char*yaffs_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call*done)

 {

      void *ret;

-#else

-static int yaffs_follow_link(structdentry *dentry, struct nameidata *nd)

-{

-      intret

-#endif

+

      unsigned char *alias;

      int ret_int = 0;

-      structyaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;

+     structyaffs_dev *dev;

 

-      yaffs_gross_lock(dev);

+     if(!dentry)

+            returnERR_PTR(-ECHILD);

 

+     dev= yaffs_dentry_to_obj(dentry)->my_dev;

+

+     yaffs_gross_lock(dev);

      alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));

      yaffs_gross_unlock(dev);

 

@@ -1074,24 +1107,14 @@

             ret_int = -ENOMEM;

             goto out;

      }

-#if (YAFFS_NEW_FOLLOW_LINK == 1)

-      nd_set_link(nd,alias);

+     set_delayed_call(done,kfree_link, alias);

      ret = alias;

 out:

      if (ret_int)

             ret = ERR_PTR(ret_int);

      return ret;

-#else

-      ret= vfs_follow_link(nd, alias);

-      kfree(alias);

-out:

-      if(ret_int)

-             ret= ret_int;

-      returnret;

-#endif

 }

 

static const struct inode_operationsyaffs_symlink_inode_operations = {

      .readlink = yaffs_readlink,

-      .follow_link= yaffs_follow_link,

-#if (YAFFS_NEW_FOLLOW_LINK == 1)

-      .put_link= yaffs_put_link,

-#endif

+     .get_link= yaffs_get_link,

      .setattr = yaffs_setattr,

-      .setxattr= yaffs_setxattr,

-      .getxattr= yaffs_getxattr,

      .listxattr = yaffs_listxattr,

-      .removexattr= yaffs_removexattr,

 };

1.7. 编译归类七

fs/yaffs2/yaffs_vfs.c:1606:2: warning:initialization from incompatible pointer type [enabled by default]

  .rename= yaffs_rename,

内核rename接口定义的变更,rename包含rename2操作。

static int yaffs_rename(struct inode*old_dir, struct dentry *old_dentry,

-                    structinode *new_dir, struct dentry *new_dentry)

+                   structinode *new_dir, struct dentry *new_dentry,

+                   unsignedint flags)

 {

      struct yaffs_dev *dev;

      int ret_val = YAFFS_FAIL;

      struct yaffs_obj *target;

 

+     if(flags)

+            return-EINVAL;

+

      yaffs_trace(YAFFS_TRACE_OS,"yaffs_rename");

1.8. 编译归类八

In file included fromfs/yaffs2/yaffs_guts.c:18:0:

fs/yaffs2/yaffs_endian.h:32:1: error:unknown type name 'Y_LOFF_T'

 static inline Y_LOFF_T swap_loff_t(Y_LOFF_Tlval)

 ^

fs/yaffs2/yaffs_endian.h:32:36: error:unknown type name 'Y_LOFF_T'

 static inline Y_LOFF_T swap_loff_t(Y_LOFF_Tlval)

未定义Y_LOFF_T,在yaffs_endian.h中加入Y_LOFF_T的定义。

#ifndef Y_LOFF_T

#define Y_LOFF_T loff_t

#endif

1.9. 编译归类九

fs/yaffs2/yaffs_nameval.c:145:5: error:conflicting types for 'nval_get'

 int nval_get(struct yaffs_dev *dev,

    ^

In file included fromfs/yaffs2/yaffs_nameval.c:28:0:

fs/yaffs2/yaffs_nameval.h:25:5: note:previous declaration of 'nval_get' was here

 int nval_get(struct yaffs_dev *dev,

    ^

fs/yaffs2/yaffs_nameval.c:185:5: error:conflicting types for 'nval_list'

 int nval_list(struct yaffs_dev *dev, constchar *xb, int xb_size, char *buf, int bsize)

    ^

In file included from fs/yaffs2/yaffs_nameval.c:28:0:

fs/yaffs2/yaffs_nameval.h:28:5: note:previous declaration of 'nval_list' was here

 int nval_list(struct yaffs_dev *dev,

头文件声明的错误,在yaffs_nameval.h中加入yaffs_guts.h头文件。

#include "yaffs_guts.h"

1.10. 编译归类十

fs/built-in.o: In function `yaffs_check_obj_details_loaded':

/usr/linux-4.10.10/fs/yaffs2/yaffs_guts.c:3254:undefined reference to `yaffs_do_endian_oh'

fs/built-in.o: In function`yaffs_oh_size_load':

/usr/linux-4.10.10/fs/yaffs2/yaffs_guts.c:5165:undefined reference to `yaffs_do_endian_u32'

/usr/linux-4.10.10/fs/yaffs2/yaffs_guts.c:5166:undefined reference to `yaffs_do_endian_u32'

fs/built-in.o: In function`yaffs_update_oh':

/usr/linux-4.10.10/fs/yaffs2/yaffs_guts.c:3401:undefined reference to `yaffs_do_endian_oh'

链接错误,Makefile中加入yaffs_endian.o

yaffs-y += yaffs_endian.o

2. 内核配置

Linux配置支持yaffs文件系统,选中File systems->Miscellaneousfilesystems->yaffs2 file system support。

Linux开发十七_yaffs文件系统_第1张图片

3. mkyaffs2image

yaffs源码包中附带了mkyaffs2image工具,mkyaffs2image工具可以把主机的某一目录内容制作成nandflash烧录镜像文件。在主机上进行编译mkyaffs2image工具时,同样会编译错误,这是工具源码与yaffs源码更新不同步,造成接口上的差异,根据错误提示更改即可。默认的mkyaffs2image工具没有ecc layout信息,一般不在mkyaffs2image工具中修改相应的ecc layout信息,由bootloader固化时更正相应的ecc layout。

./mkyaffs2image  /root/rootfs/busybox  rootfs.bin

4. 固化启动

笔者的bootloader可以实现从sd卡更新bootloader、内核、根文件系统。

更改bootloader的启动参数,使之从nandflash挂载根文件系统,编译并把生成的二进制代码文件重命名为bootloader.bin放在sd卡/image目录下。

const char BootCmd[] = "noinitrd root=/dev/mtdblock3rootfstype=yaffs2 init=/init console=ttySAC0";

更改Linux内核的配置,取消initramfs根文件系统,重新编译,生成的zImage重命名为kernel.bin放在sd卡/image目录下。

mkyaffs2image工具制作的yaffs根文件系统镜像文件rootfs.bin放在sd卡/image目录下。

通过串口,按住空格键上电启动,bootloader将进入到下载模式,选择从sd卡更新bootloader、kernel、rootfs到nand flash。

从nand flash启动Linux系统。

Linux开发十七_yaffs文件系统_第2张图片

5. 附录

https://pan.baidu.com/s/1slczwhJ

bootloader源码以及使用说明

https://pan.baidu.com/s/1eRDJtNs

Qt5.8官网源码

https://pan.baidu.com/s/1nuGmSqt

本系列例程的根文件系统

https://pan.baidu.com/s/1i5btLGT

opev3.2.0官网源码

https://pan.baidu.com/s/1pLpuHw3

yaffs官网源码 

https://pan.baidu.com/s/1bpkZynt

busybox-1.26.2官网源码

https://pan.baidu.com/s/1i4EtjfR

tslib官网源码

https://pan.baidu.com/s/1i5MGRhb

mplayer-1.3.0官网源码

https://pan.baidu.com/s/1sl0fXlr

基于S3C2416修改的linux-4.10.10源码

 

你可能感兴趣的:(嵌入式linux开发,linux内核,s3c2416,nand,yaffs)