Jffs2文件系统移植时不能写

时间:2021-05-14 09:06:35
我的板子*M的flash空间,我划了5个MTD分区 
0x000000-------0x40000) bootloader 
0x40000-------------x700000 linux kernel + rootfs(squashfs) 
0x700000-------9x7f0000) jffs2 
0x7f0000-------9x800000) nvram 

开始jffs2分区并没有使用, 所以我想在里面建立第二个可写的文件系统,一切准备就绪之后,mount到了根文件系统之上,ls cat这些涉及读操作的命令都很正常, 可是只要是涉及写操作的命令就报告错误Input/output error, 最后我跟踪内核代码看了,发现是在MTD的驱动里面的mtd->write()函数出现了问题。 比方chmod这条命令,最后在内核代码中追踪到mtd_writev(xxxxx)这个函数时,本来是往flash中写入68个byte,最后返回的结果是写进去了68*2=136 byte, 怎么会出现这种现象? 我的flash芯片是intel CFI 接口的nor flash, 支持的cmdset不清楚, 我对底层的flash芯片运作的机制不是很懂,所以搞了一个多星期这个问题还没有解决,请各位大侠帮忙指点一下怎么解决啊!、、、 
注意我的jffs2分区是以rw的方式挂载的,我换了几个mkfs.jffs2工具制作文件系统image 都是这样的问题。 我的内核版本是2.4.20 我怀疑是MTD最底层的mtd_info->write( )这个函数出了问题, 可是怎么也不知道它到底哪里出了问题 

16 个解决方案

#1


最后返回的结果是写进去了68*2=136 byte, 怎么会出现这种现象
================================
jffs2 文件系统在 flash   里写入一些 jffs2 分区特有的信息。

struct jffs2_raw_inode
{
__u16 magic;      /* A constant magic number.  */
__u16 nodetype;   /* == JFFS_NODETYPE_INODE */
__u32 totlen;     /* Total length of this node (inc data, etc.) */
__u32 hdr_crc;
__u32 ino;        /* Inode number.  */
__u32 version;    /* Version number.  */
__u32 mode;       /* The file's type or mode.  */
__u16 uid;        /* The file's owner.  */
__u16 gid;        /* The file's group.  */
__u32 isize;      /* Total resultant size of this inode (used for truncations)  */
__u32 atime;      /* Last access time.  */
__u32 mtime;      /* Last modification time.  */
__u32 ctime;      /* Change time.  */
__u32 offset;     /* Where to begin to write.  */
__u32 csize;      /* (Compressed) data size */
__u32 dsize;   /* Size of the node's data. (after decompression) */
__u8 compr;       /* Compression algorithm used */
__u8 usercompr;   /* Compression algorithm requested by the user */
__u16 flags;   /* See JFFS2_INO_FLAG_* */
__u32 data_crc;   /* CRC for the (compressed) data.  */
__u32 node_crc;   /* CRC for the raw inode (excluding data)  */
// __u8 data;   
} __attri

而这个结构的大小刚好是  68 byte

建议你用 mtd_util 工具格式化一下分区, 然后直接把你 用 mkfs.jffs2 做出来的包 dd 进该分区.
/bin/dd if=/mnt/rootfs.jffs2 of=/dev/mtdblock2

#2


我进行的是chmod操作,setAttr写进去的就只是是一个struct jffs2_raw_inode 结构  就是这个68bytes
可是mtd_writev却写进去了136byte   返回时代码检查写进去的长度不一样  就返回了
metadata error

    我的板子上没有mtd_util 工具  编译不通过   格式化就是实用erase命令擦除分区吗??还是像磁盘那样格式化????

#3


我进行的是chmod操作,setAttr写进去的就只是是一个struct jffs2_raw_inode 结构  就是这个68bytes 
可是mtd_writev却写进去了136byte 
============================================================
这个我不确定, chmod 的时候要修改文件的属性,也就是说会修改文件的 inode,
至于写了多少字节,我不确定,应为没有读过jffs2 写文件部分的代码,只看过读文件部分的代码,所以不确定。

返回时代码检查写进去的长度不一样  就返回了
========================================
这个可能和硬件的时序有关系,也就是说,驱动有问题,等待操作flash的时间可能需要修改, nand flash 的我倒是知道,
nor flash的没接触过。 不过,你可以查看一下nor flash相关部分的代码。 这个跟jffs2 是没有关系的。

我的板子上没有mtd_util 工具  编译不通过   格式化就是实用erase命令擦除分区吗??还是像磁盘那样格式化???? 
==================================
mtd_util 工具可以从网上下载, 格式化就是用 flash_eraseall 命令 比如:
flash_eraseall /dev/mtd2 
注意擦出需要按字符设备去擦, 也就是  mtd2


#4


我使用dd命令试了,还是出现相同的问题。 确实是flash芯片驱动的问题,板子上以前运行的都是只读的文件系统,
所以每发现这个问题,现在用jffs2只要是调用到mtd->write,问题就来了  

我研究了下flash chip的驱动,发现不是内核中自带的cfi flash驱动(我开始是这么以为 
的),现在发现是broadcom自己写的驱动代码在 
mtd/device/sflash.c中, 可是就是奇怪,为什么烧代码时能写进去呢? 无论是在bootloader还是在 
内核启动后通过tftp协议打开/dev/mtdblock/3块设备来烧,最终都调用的是同一个mtd->write(即sflash_write)这个函数,唯一的区别就是在烧代码时往里面写之前会调用mtd->erase(即sflash_erase),在 
jffs2文件系统中因为写的字节比较少,我看就是直接调用的mtd->write,没有调用mtd->erase,是不是 
因为这个差别的原因? 
我想调用mtd->write()往flash写少量数据时,如果不足一个扇区,要先擦除这个扇区再写, 
这应该是mtd->write()函数里面完成的事情吧?还是在调用mtd->write之前,一定要调用mtd->erase 
手动擦除?? 难道ST serial flash只能整块整块写 不能随机写吧??

#5


MTD可以写要条件的。边界与MTD的大小要符合一个条件。

#6


来学习的    

#7


如果其他的分区可以写,那么jffs2区不能写就是驱动的问题

如果是驱动问题,建议楼主移植个2.6的内核对比下,如果2.6的内核可以解决,如果一定要用2.4的内核,也可以把高2.6版本的移植到2.4

#8


在bootloader那边把该分区给擦掉后再试试看。有可能分区里面原先有东西,而且该分区已经写满了。有可能会出现这样的问题。

#9


jffs2文件系统中因为写的字节比较少,我看就是直接调用的mtd->write,没有调用mtd->erase,是不是 
因为这个差别的原因? 
========================================================================
nand flash 在写之前是一定会erase, 这是硬件特性决定的。
mtdblock 这一层会先缓存数据,等数据达到一定数量,或者 sync 被调用才会去写数据。
写的最小单位是 一个page, 擦除的最小单位是一个block。

nor flash 我不确定,你应该去研究一下 nor flash的工作原理。

 

#10


mtdblock 这一层会先缓存数据  等数据达到一定数量,或者 sync 被调用才会去写数据。 
=================================================

我用的是NOR Flash, jffs2文件系统中是直接调用mtd->write(),mtd->write()中没有进行数据缓存,
而直接把不足一个block的数据写进去,mtd->write是flash驱动定义的一个callback函数,我就怀疑这里
是不是有问题? 
 再者,烧写jffs2文件系统的分区开始地址0x700000-----------0x7f0000
边界已经对齐  大小960KB 应该没问题了吧?

#11


我就奇怪,烧代码时调用的也是mtd->write()函数,jffs2中调用的也是mtd->write,同一个函数,
为什么在jffs2中调用就出了问题呢?

#12


烧写的时候是通过 uboot 烧写的吗?

#13


通过自己板子上的bootloader烧  或kernel启动后通过tftp应用烧都没问题

#14


直接用 dd 往分区里写数据会出错吗? 如果不会,那说明确实是 jffs2的问题了。

#15


直接用 dd 出现的问题是一样的   不是烧image时出了问题 否则mount ls cat 怎么正常?

#16


第四个nvram分区本来能写的,加大了jffs2的大小后(超过1M后),往nvram分区写时同样也报告Input/output error
怎么这么奇怪, 并没有改变nvram分区的大小了起始地址啊, 并且jffs2的大小也不是太大,没有覆盖前面的rootfs
分区

#1


最后返回的结果是写进去了68*2=136 byte, 怎么会出现这种现象
================================
jffs2 文件系统在 flash   里写入一些 jffs2 分区特有的信息。

struct jffs2_raw_inode
{
__u16 magic;      /* A constant magic number.  */
__u16 nodetype;   /* == JFFS_NODETYPE_INODE */
__u32 totlen;     /* Total length of this node (inc data, etc.) */
__u32 hdr_crc;
__u32 ino;        /* Inode number.  */
__u32 version;    /* Version number.  */
__u32 mode;       /* The file's type or mode.  */
__u16 uid;        /* The file's owner.  */
__u16 gid;        /* The file's group.  */
__u32 isize;      /* Total resultant size of this inode (used for truncations)  */
__u32 atime;      /* Last access time.  */
__u32 mtime;      /* Last modification time.  */
__u32 ctime;      /* Change time.  */
__u32 offset;     /* Where to begin to write.  */
__u32 csize;      /* (Compressed) data size */
__u32 dsize;   /* Size of the node's data. (after decompression) */
__u8 compr;       /* Compression algorithm used */
__u8 usercompr;   /* Compression algorithm requested by the user */
__u16 flags;   /* See JFFS2_INO_FLAG_* */
__u32 data_crc;   /* CRC for the (compressed) data.  */
__u32 node_crc;   /* CRC for the raw inode (excluding data)  */
// __u8 data;   
} __attri

而这个结构的大小刚好是  68 byte

建议你用 mtd_util 工具格式化一下分区, 然后直接把你 用 mkfs.jffs2 做出来的包 dd 进该分区.
/bin/dd if=/mnt/rootfs.jffs2 of=/dev/mtdblock2

#2


我进行的是chmod操作,setAttr写进去的就只是是一个struct jffs2_raw_inode 结构  就是这个68bytes
可是mtd_writev却写进去了136byte   返回时代码检查写进去的长度不一样  就返回了
metadata error

    我的板子上没有mtd_util 工具  编译不通过   格式化就是实用erase命令擦除分区吗??还是像磁盘那样格式化????

#3


我进行的是chmod操作,setAttr写进去的就只是是一个struct jffs2_raw_inode 结构  就是这个68bytes 
可是mtd_writev却写进去了136byte 
============================================================
这个我不确定, chmod 的时候要修改文件的属性,也就是说会修改文件的 inode,
至于写了多少字节,我不确定,应为没有读过jffs2 写文件部分的代码,只看过读文件部分的代码,所以不确定。

返回时代码检查写进去的长度不一样  就返回了
========================================
这个可能和硬件的时序有关系,也就是说,驱动有问题,等待操作flash的时间可能需要修改, nand flash 的我倒是知道,
nor flash的没接触过。 不过,你可以查看一下nor flash相关部分的代码。 这个跟jffs2 是没有关系的。

我的板子上没有mtd_util 工具  编译不通过   格式化就是实用erase命令擦除分区吗??还是像磁盘那样格式化???? 
==================================
mtd_util 工具可以从网上下载, 格式化就是用 flash_eraseall 命令 比如:
flash_eraseall /dev/mtd2 
注意擦出需要按字符设备去擦, 也就是  mtd2


#4


我使用dd命令试了,还是出现相同的问题。 确实是flash芯片驱动的问题,板子上以前运行的都是只读的文件系统,
所以每发现这个问题,现在用jffs2只要是调用到mtd->write,问题就来了  

我研究了下flash chip的驱动,发现不是内核中自带的cfi flash驱动(我开始是这么以为 
的),现在发现是broadcom自己写的驱动代码在 
mtd/device/sflash.c中, 可是就是奇怪,为什么烧代码时能写进去呢? 无论是在bootloader还是在 
内核启动后通过tftp协议打开/dev/mtdblock/3块设备来烧,最终都调用的是同一个mtd->write(即sflash_write)这个函数,唯一的区别就是在烧代码时往里面写之前会调用mtd->erase(即sflash_erase),在 
jffs2文件系统中因为写的字节比较少,我看就是直接调用的mtd->write,没有调用mtd->erase,是不是 
因为这个差别的原因? 
我想调用mtd->write()往flash写少量数据时,如果不足一个扇区,要先擦除这个扇区再写, 
这应该是mtd->write()函数里面完成的事情吧?还是在调用mtd->write之前,一定要调用mtd->erase 
手动擦除?? 难道ST serial flash只能整块整块写 不能随机写吧??

#5


MTD可以写要条件的。边界与MTD的大小要符合一个条件。

#6


来学习的    

#7


如果其他的分区可以写,那么jffs2区不能写就是驱动的问题

如果是驱动问题,建议楼主移植个2.6的内核对比下,如果2.6的内核可以解决,如果一定要用2.4的内核,也可以把高2.6版本的移植到2.4

#8


在bootloader那边把该分区给擦掉后再试试看。有可能分区里面原先有东西,而且该分区已经写满了。有可能会出现这样的问题。

#9


jffs2文件系统中因为写的字节比较少,我看就是直接调用的mtd->write,没有调用mtd->erase,是不是 
因为这个差别的原因? 
========================================================================
nand flash 在写之前是一定会erase, 这是硬件特性决定的。
mtdblock 这一层会先缓存数据,等数据达到一定数量,或者 sync 被调用才会去写数据。
写的最小单位是 一个page, 擦除的最小单位是一个block。

nor flash 我不确定,你应该去研究一下 nor flash的工作原理。

 

#10


mtdblock 这一层会先缓存数据  等数据达到一定数量,或者 sync 被调用才会去写数据。 
=================================================

我用的是NOR Flash, jffs2文件系统中是直接调用mtd->write(),mtd->write()中没有进行数据缓存,
而直接把不足一个block的数据写进去,mtd->write是flash驱动定义的一个callback函数,我就怀疑这里
是不是有问题? 
 再者,烧写jffs2文件系统的分区开始地址0x700000-----------0x7f0000
边界已经对齐  大小960KB 应该没问题了吧?

#11


我就奇怪,烧代码时调用的也是mtd->write()函数,jffs2中调用的也是mtd->write,同一个函数,
为什么在jffs2中调用就出了问题呢?

#12


烧写的时候是通过 uboot 烧写的吗?

#13


通过自己板子上的bootloader烧  或kernel启动后通过tftp应用烧都没问题

#14


直接用 dd 往分区里写数据会出错吗? 如果不会,那说明确实是 jffs2的问题了。

#15


直接用 dd 出现的问题是一样的   不是烧image时出了问题 否则mount ls cat 怎么正常?

#16


第四个nvram分区本来能写的,加大了jffs2的大小后(超过1M后),往nvram分区写时同样也报告Input/output error
怎么这么奇怪, 并没有改变nvram分区的大小了起始地址啊, 并且jffs2的大小也不是太大,没有覆盖前面的rootfs
分区