• Linux PC上挂载JFFS2文件系统

    声明:本文转载于EMAC Wiki的文章《Mounting JFFS2 Images on a Linux PC》。

    Mounting JFFS2 Images on a Linux PC


    It is possible to mount a binary JFFS2 image on a Linux PC without a flash device. This can be useful for examining the contents of the image, making required changes, and creating a new image in any format. When a JFFS2 image is copied directly from a JFFS2 flash partition, the resulting image is the size of the source partition, regardless of how much space is actually used for storage. Mounting the filesystem and using the mkfs.jffs2 utility to create a new image will result in a JFFS2 image without blank nodes. This can also be used to create multiple images for flashes with different characteristics, such as erase block sizes. This page describes two different methods of mounting JFFS2 images on a Linux PC.

    Mounting JFFS2 Images using RAM


    One method of mounting JFFS2 images uses the mtdram module to emulate an MTD device using system RAM. This works well for JFFS2 images that are less than approximately 32 MB but will not work for larger images since it requires allocating a large amount of system RAM. The basic steps of this process are as follows:

    1. Load mtdram and mtdblock modules.
    2. Use the dd command to copy the JFFS2 image to /dev/mtdblock0.
    3. Mount /dev/mtdblock0 as a JFFS2 filesytem.

    In order to simplify this process, EMAC has created a script which takes the JFFS2 image, mount point, and the erase block size of the image as parameters. The default erase block size for this script is 128 KiB, which is the correct value for most NOR flashes used on EMAC products and some NAND flashes. The eraseblock size can be determined from the contents of /proc/mtd from the system that the image was copied from or created for. For example, if the value of the “erasesize” parameter is 00040000, the erase block size for the device is 256 KiB (0x40000 = 262144 bytes, 262144 / 1024 = 256 KiB). The jffs2_mount_mtdram.sh script is shown below.

    #!/bin/bash
    
    ## Script to mount jffs2 filesystem using mtd kernel modules.
    ## EMAC, Inc. 2009
    
    if [[ $# -lt 2 ]]
    then
        echo "Usage: $0 FSNAME.JFFS2 MOUNTPOINT [ERASEBLOCK_SIZE]"
        exit 1
    fi
    
    if [ "$(whoami)" != "root" ]
    then
        echo "$0 must be run as root!"
        exit 1
    fi
    
    if [[ ! -e $1 ]]
    then
        echo "$1 does not exist"
        exit 1
    fi
    
    if [[ ! -d $2 ]]
    then
        echo "$2 is not a valid mount point"
        exit 1
    fi
    
    if [[ "$3" == "" ]]
    then
            esize="128"
    else
            esize="$3"
    fi
    
    # cleanup if necessary
    umount /dev/mtdblock0 &>/dev/null
    modprobe -r mtdram &>/dev/null
    modprobe -r mtdblock &>/dev/null
    
    modprobe mtdram total_size=32768 erase_size=$esize || exit 1
    modprobe mtdblock || exit 1
    dd if="$1" of=/dev/mtdblock0 || exit 1
    mount -t jffs2 /dev/mtdblock0 $2 || exit 1
    
    echo "Successfully mounted $1 on $2"
    exit 0

    To mount an image with 256 KiB erase block size named rootfs.jffs2 on /mnt/jffs2 using jffs2_mount_mtdram.sh, run the script as shown below:

    developer@ldc:~$ sudo ./jffs2_mount_mtdram.sh rootfs.jffs2 /mnt/jffs2 256

    Once this has been done, the contents of the image should be accessible at /mnt/jffs2.

    Mounting JFFS2 Images using a Loop Device


    A second method for mounting JFFS2 images utilizes a loop device. This method is appropriate for larger images that cannot be mounted successfully with the mtdram approach. The process requires the following steps:

    1. Load loop, block2mtd, and jffs2 modules
    2. Create a loop device
    3. Set the block2mtd parameters for the loop device
    4. Mount the JFFS2 image

    EMAC has created a script to simplify this process that takes the JFFS2 image, mount point, and image erase block size as parameters. The default erase block size for this script is 128 KiB, which is the correct value for most NOR flashes used on EMAC products and some NAND flashes. See the description of determining the correct erase block size to use in the previous section. The jffs2_mount_loop.sh script is shown below.

    #!/bin/bash
    
    ## Script to mount jffs2 filesystem using mtd kernel modules.
    ## EMAC, Inc. 2011
    
    if [[ $# -lt 2 ]]
    then
        echo "Usage: $0 FSNAME.JFFS2 MOUNTPOINT [ERASEBLOCK_SIZE]"
        exit 1
    fi
    
    if [ "$(whoami)" != "root" ]
    then
        echo "$0 must be run as root!"
        exit 1
    fi
    
    if [[ ! -e $1 ]]
    then
        echo "$1 does not exist"
        exit 1
    fi
    
    if [[ ! -d $2 ]]
    then
        echo "$2 is not a valid mount point"
        exit 1
    fi
    
    if [[ "$3" == "" ]]
    then
            esize="128"
    else
            esize="$3"
    fi
    
    # cleanup if necessary
    umount /tmp/mtdblock0 &>/dev/null
    umount $2 &>/dev/null
    modprobe -r jffs2 &>/dev/null
    modprobe -r block2mtd &>/dev/null
    modprobe -r mtdblock &>/dev/null
    sleep 0.25
    losetup -d /dev/loop1 &>/dev/null
    sleep 0.25
    
    modprobe loop || exit 1
    losetup /dev/loop1 "$1" || exit 1
    modprobe block2mtd || exit 1
    modprobe jffs2 || exit 1
    if [[ ! -e /tmp/mtdblock0 ]]
    then
        mknod /tmp/mtdblock0 b 31 0 || exit 1
    fi
    
    echo "/dev/loop1,${esize}KiB" > /sys/module/block2mtd/parameters/block2mtd
    
    mount -t jffs2 /tmp/mtdblock0 "$2" || exit 1
    
    echo "Successfully mounted $1 on $2"
    exit 0

    Usage for this script is identical to the jffs2_mount_mtdram.sh script discussed in the previous section.

    展开全文
  • 参考链接: ... ... 如何将一个mtd ram 设备格式化为jffs2文件系统并且正常使用? 1kernel 配置: (1)jffs2文件系统支持: File systems —>...

    参考链接:
    http://www.linuxdiyf.com/viewarticle.php?id=58126
    http://blog.chinaunix.net/uid-26683644-id-3394110.html
    如何将一个ram mtd设备格式化为jffs2文件系统并且正常使用?
    1.kernel 配置:

    (1)jffs2文件系统支持:
    File systems  --->
     -*- Miscellaneous filesystems  ---> 
          <*>   Journalling Flash File System v2 (JFFS2) support                                                              
         (0)     JFFS2 debugging verbosity (0 = quiet, 2 = noisy)                                                           
         [*]     JFFS2 write-buffering support                                                                                  
         [*]       Verify JFFS2 write-buffer reads                                                                            
         [*]     JFFS2 summary support                                                                                       
         [*]     JFFS2 XATTR support                                                                                           
         [*]       JFFS2 POSIX Access Control Lists                                                                            
         [*]       JFFS2 Security Labels                                                                                       
         [ ]     Advanced compression options for JFFS2
    

    (2) ram mtd 支持

     Device Drivers  ---> 
     <*> Memory Technology Device (MTD) support  --->
         <*>   Caching block device access to MTD devices
         Self-contained MTD device drivers  ---> 
             <*> Test driver using RAM                                                                                             
                      (8192) MTDRAM device size in KiB                                                                                     
                      (128) MTDRAM erase block size in KiB
    

    说明:这个配置让kernel把一块内存区域虚拟成一片flash给你使用。
    8192 这里指分配8M的内存大小,系统启动后/dev/会有个8M大小的块设备。
    128  指擦除块大小
    2.jffs2文件系统制作:
    这步操作在UBUNTU主机上执行,目的是为了得到一个jffs2镜像文件
    mkfs.jffs2 -s 0x1000 -e 0x20000 -p 0x800000 -d jffs2-file/ -o jffs2.img
    说明:-p 0x800000 指生成8M大小的镜像,这个大小要和你kernel配置的一致:
    (8192) MTDRAM device size in KiB
    -e 0x2000 快擦除大小128K,与(128) MTDRAM erase block size in KiB一致。
    3.使用
    以下操作在target上执行
    (1)将上一步得到的jffs2.img拷贝到target /jffs2.img
    (2) dd if=/jffs2.img of=/dev/mtdblock0
    (3) mkdir test; mount -t jffs2 /dev/mtdblock0 test
    (4)查看是否成功:
    root@intel-x86-64:~# mount
    /dev/mtdblock0 on /root/test type jffs2 (rw,relatime)
    (5) 读写测试:
    cd /root/test; cp /sbin/init .

    展开全文
  • Linux Uboot支持访问JFFS2文件系统 最近要做一小任务:uboot中添加对jffs2文件系统访问。 本人参考了网上好些博文和帖子,上面基本上就是添加几个宏定义就可以了,例如: 又例如: 按照网上在自己板级配置文件...

    Linux Uboot支持访问JFFS2文件系统

    最近要做一小任务:uboot中添加对jffs2文件系统访问。
    本人参考了网上好些博文和帖子,上面基本上就是添加几个宏定义就可以了,例如:
    网上博客部分截图
    又例如:
    网上博客部分截图

    按照网上在自己板级配置文件中添加上述几个宏定义,发现uboot起不来,总是卡在下图中的位置:
    uboot启动截图
    然后我就蒙逼了,不知道卡在了什么地方,连续2天没头绪,后来觉得不行,自己又看了uboot中关于jffs2的cmd命令部分(common/cmd_jffs2.c)以及jffs2文件系统代码(fs/jffs2/jffs2_1pass.c),经过一番思考,添加了了一些代码修改,终于,完成了uboot对于jffs2文件系统的访问。

    添加的板级配置宏定义命令如下(我的板子上面是norflash,所以为nor0,CONFIG_JFFS2_PART_OFFSET这个是jffs2文件系统在flash中的偏移位置,CONFIG_JFFS2_PART_SIZE这个是jffs2文件系统大小,其他宏定义均为自己根据本平台进行添加的):
    宏定义配置截图
    另外common目录下修改了原来的cmd_jffs2.c中fsload命令,ls命令,fsinfo命令相关函数(每次使用这三个命令开始处都会把flash中jffs2文件系统map到内存中),增加了一个命令fsdump(uboot中打印jffs2文件系统中的文件内容),最关键的还是添加了把flash中jffs2文件系统map到内存中,没有这个还是不行的,总之别人写得再好那也是别人的,自己还是要根据自己实际uboot代码来修改呀。。。

    最终效果如下:
    (1)ls
    ls命令uboot打印截图

    (2)fsinfo
    fsinfo命令uboot打印截图
    (3)fsload
    fsload命令uboot打印截图

    (4)fsdump
    fsdump命令uboot打印截图
    要想上电就从jffs2文件系统中读取uImage并启动,直接修改环境变量即可,本版中,直接修改:
    bootcmd=sf probe;sf read 0x80600000 0x40000 0x280000; bootm 0x80600000 (原来从flash启动)
    bootcmd=fsload 0x80600000 uImage;bootm 0x80600000 (现在从jffs2文件系统读取image启动,可以节省一个image分区)

    任务完成,gg(思考第一,观察第二)

    下面是我的个人公众号,喜欢linux c,c++,嵌入式的欢迎加入:
    在这里插入图片描述

    展开全文
  • margin: 2cm } P { margin-bottom: 0.21cm } --> 我们在调试硬件板时,经常需要做多个jffs2的根文件系统映像,有时也要对比其他途径得到的可用的jffs2根文件系统映像。但jffs2的文件系统映像不象光盘

    我们在调试硬件板时,经常需要做多个jffs2的根文件系统映像,有时也要对比其他途径得到的可用的jffs2根文件系统映像。但jffs2的文件系统映像不象光盘的映像文件一样可以通过loop设备来挂载,总不可能一个个烧录到硬件板去看吧。

    后来到网上google了一把,左翻右翻之后总算找到了一个方法。因为jffs2是构建于MTD设备上的文件系统,所以无法通过loop设备来挂载,但是可以通过mtdram设备来挂载。mtdram是在用RAM实现的MTD设备,可以通过mtdblock设备来访问。使用mtdram设备很简单,只要加载mtdrammtdblock两个内核模块即可。这两个内核模块一般的linux内核发行版都有编译好的,直接用modprobe命令加载。

    下面是在Fedora core 6环境下使用mtdram设备挂载jffs2根文件系统映像的具体步骤:

    1.加载mtdblock内核模块

    [root@localhost ~]# modprobe mtdblock

    2.加载mtdram内核模块,将该设备的大小指定为jffs2根文件系统映像的大小,块擦除大小(即flash的块大小)指定为制作该jffs2根文件系统时“-e”参数指定的大小,缺省为64KB。下面两个参数的单位都是KB

    [root@localhost ~]# modprobe mtdram total_size=49152 erase_size=128

    3.这时将出现MTD设备/dev/mtdblock0,使用dd命令将jffs2根文件系统拷贝到/dev/mtdblock0设备中。

    [root@localhost prebuilt_bin]# dd if=rootfs.jffs2_zylonite_qvga of=/dev/mtdblock0

    98304+0 records in

    98304+0 records out

    50331648 bytes (50 MB) copied, 1.98391 seconds, 25.4 MB/s

    4.将保存了jffs2根文件系统的MTD设备挂载到指定的目录上。

    [root@localhost prebuilt_bin]# mount -t jffs2 /dev/mtdblock0 /mnt/mtd

    这之后就可以到/mnt/mtd目录查看、修改挂载的jffs2根文件系统了,修改后的jffs2根文件系统可以通过dd命令拷贝为一个jffs2的映像文件。

     
    展开全文
  • JFFS2

    2019-04-27 16:38:16
    文章目录一、JFFS2介绍1、JFFS2简介2JFFS2框架二、JFFS2实现1、JFFS2的机制2JFFS2数据结构1)struct jffs2_sb_info3、其它数据结构1)struct super_block附录1、参考资料 一、JFFS2介绍 1、JFFS2简介 2JFFS2...

    一、JFFS2介绍


    1、JFFS2简介

    2、JFFS2框架

    1)VFS
    VFS框架
    2)MTD
    MTD层次

    二、JFFS2实现


    1、JFFS2的机制

    2、JFFS2数据结构

    1)struct jffs2_sb_info

    该结构体用于描述jffs2文件系统super block的信息。(fs/jffs2/jffs2_fs_sb.h

    struct jffs2_sb_info {
    		/* @mtd: 文件系统所在flash分区的mtd信息 */
    		struct mtd_info *mtd;
    		/* @highest_ino: 记录文件系统内最高的索引结点号,当新建文件时,系统为之分配的
    		 *     索引结点号就是highest_ino,并将该字段值递增。 */
    		uint32_t highest_ino;
    		uint32_t check_ino;		/* *NEXT* inode to be checked */
    		/* @flags: 挂载文件系统时指定的各种标志,如:JFFS2_SB_FLAG_RO (只读)... */
    		unsigned int flags;
    
    		struct task_struct *gc_task;	/* GC task struct */
    		struct completion gc_thread_start; /* GC thread start completion */
    		struct completion gc_thread_exit; /* GC thread exit completion port */
    	
    		struct mutex alloc_sem;		/* Used to protect all the following
    						   fields, and also to protect against
    						   out-of-order writing of nodes. And GC. */
    		uint32_t cleanmarker_size;	/* Size of an _inline_ CLEANMARKER
    						 (i.e. zero for OOB CLEANMARKER */
    
    		/* 对应flash分区的大小 */
    		uint32_t flash_size; // copy from @mtd_info.size
    		uint32_t used_size;
    		uint32_t dirty_size;
    		uint32_t wasted_size;
    		uint32_t free_size;
    		uint32_t erasing_size;
    		uint32_t bad_size;
    		uint32_t sector_size;
    		uint32_t unchecked_size;
    
    	uint32_t nr_free_blocks;
    	uint32_t nr_erasing_blocks;
    
    	/* Number of free blocks there must be before we... */
    	uint8_t resv_blocks_write;	/* ... allow a normal filesystem write */
    	uint8_t resv_blocks_deletion;	/* ... allow a normal filesystem deletion */
    	uint8_t resv_blocks_gctrigger;	/* ... wake up the GC thread */
    	uint8_t resv_blocks_gcbad;	/* ... pick a block from the bad_list to GC */
    	uint8_t resv_blocks_gcmerge;	/* ... merge pages when garbage collecting */
    	/* Number of 'very dirty' blocks before we trigger immediate GC */
    	uint8_t vdirty_blocks_gctrigger;
    
    	uint32_t nospc_dirty_size;
    
    		uint32_t nr_blocks;
    		struct jffs2_eraseblock *blocks;	/* The whole array of blocks. Used for getting blocks
    							 * from the offset (blocks[ofs / sector_size]) */
    		struct jffs2_eraseblock *nextblock;	/* The block we're currently filling */
    	
    		/* @gcblock: 指向当前应该被垃圾收集的擦除块,如果为NULL,可通过 
    		 *     @jffs2_find_gc_block找到应该被垃圾收集的擦除块。 */
    		struct jffs2_eraseblock *gcblock;
    
    		struct list_head clean_list;		/* Blocks 100% full of clean data */
    		struct list_head very_dirty_list;	/* Blocks with lots of dirty space */
    		struct list_head dirty_list;		/* Blocks with some dirty space */
    		struct list_head erasable_list;		/* Blocks which are completely dirty, and need erasing */
    		struct list_head erasable_pending_wbuf_list;	/* Blocks which need erasing but only after the current wbuf is flushed */
    		struct list_head erasing_list;		/* Blocks which are currently erasing */
    		struct list_head erase_checking_list;	/* Blocks which are being checked and marked */
    		struct list_head erase_pending_list;	/* Blocks which need erasing now */
    		struct list_head erase_complete_list;	/* Blocks which are erased and need the clean marker written to them */
    		struct list_head free_list;		/* Blocks which are free and ready to be used */
    		struct list_head bad_list;		/* Bad blocks. */
    		struct list_head bad_used_list;		/* Bad blocks with valid data in. */
    
    	spinlock_t erase_completion_lock;	/* Protect free_list and erasing_list
    						   against erase completion handler */
    	wait_queue_head_t erase_wait;		/* For waiting for erases to complete */
    
    	wait_queue_head_t inocache_wq;
    	int inocache_hashsize;
    	struct jffs2_inode_cache **inocache_list;
    	spinlock_t inocache_lock;
    
    	/* Sem to allow jffs2_garbage_collect_deletion_dirent to
    	   drop the erase_completion_lock while it's holding a pointer
    	   to an obsoleted node. I don't like this. Alternatives welcomed. */
    	struct mutex erase_free_sem;
    
    	uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
    
    #ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
    	unsigned char *wbuf_verify; /* read-back buffer for verification */
    #endif
    #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
    	unsigned char *wbuf; /* Write-behind buffer for NAND flash */
    	uint32_t wbuf_ofs;
    	uint32_t wbuf_len;
    	struct jffs2_inodirty *wbuf_inodes;
    	struct rw_semaphore wbuf_sem;	/* Protects the write buffer */
    
    	struct delayed_work wbuf_dwork; /* write-buffer write-out work */
    
    	unsigned char *oobbuf;
    	int oobavail; /* How many bytes are available for JFFS2 in OOB */
    #endif
    
    	struct jffs2_summary *summary;		/* Summary information */
    	struct jffs2_mount_opts mount_opts;
    
    #ifdef CONFIG_JFFS2_FS_XATTR
    #define XATTRINDEX_HASHSIZE	(57)
    	uint32_t highest_xid;
    	uint32_t highest_xseqno;
    	struct list_head xattrindex[XATTRINDEX_HASHSIZE];
    	struct list_head xattr_unchecked;
    	struct list_head xattr_dead_list;
    	struct jffs2_xattr_ref *xref_dead_list;
    	struct jffs2_xattr_ref *xref_temp;
    	struct rw_semaphore xattr_sem;
    	uint32_t xdatum_mem_usage;
    	uint32_t xdatum_mem_threshold;
    #endif
    	/* OS-private pointer for getting back to master superblock info */
    	void *os_priv;
    };
    

    2)struct jffs2_inode_info

    该结构体用于描述jffs2文件系统inode的信息。(fs/jffs2/jffs2_fs_i.h

    struct jffs2_inode_info {
    	/* We need an internal mutex similar to inode->i_mutex.
    	   Unfortunately, we can't used the existing one, because
    	   either the GC would deadlock, or we'd have to release it
    	   before letting GC proceed. Or we'd have to put ugliness
    	   into the GC code so it didn't attempt to obtain the i_mutex
    	   for the inode(s) which are already locked */
    	struct mutex sem;
    
    	/* The highest (datanode) version number used for this ino */
    	uint32_t highest_version;
    
    	/* List of data fragments which make up the file */
    	struct rb_root fragtree;
    
    	/* There may be one datanode which isn't referenced by any of the
    	   above fragments, if it contains a metadata update but no actual
    	   data - or if this is a directory inode */
    	/* This also holds the _only_ dnode for symlinks/device nodes,
    	   etc. */
    	struct jffs2_full_dnode *metadata;
    
    	/* Directory entries */
    	struct jffs2_full_dirent *dents;
    
    	/* The target path if this is the inode of a symlink */
    	unsigned char *target;
    
    	/* Some stuff we just have to keep in-core at all times, for each inode. */
    	struct jffs2_inode_cache *inocache;
    
    	uint16_t flags;
    	uint8_t usercompr;
    	struct inode vfs_inode;
    };
    

    3)struct jffs2_raw_node_ref

    一个文件对应一个 jffs2_inode_cache,同时对应多个jffs2_raw_node_ref

    struct jffs2_raw_node_ref
    {
    		/* @next_in_ino: 单向链表,指向下一个raw_node_ref,如果这是最后一个成员,
    		 *     则会指向 @jffs2_inode_cache,参见函数jffs2_raw_ref_to_ic(),
    		 *     如此一来,每个 @jffs2_raw_node_ref 都知道自己所在的文件了。
    		 */
    		struct jffs2_raw_node_ref *next_in_ino;
    		/* @flash_offset: 表示相应数据实体在flash分区上的物理地址 */
    		uint32_t flash_offset;
    #undef TEST_TOTLEN
    #ifdef TEST_TOTLEN
    		uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
    #endif
    };
    

    4)struct jffs2_inode_cache

    struct jffs2_inode_cache {
    		/* First part of structure is shared with other objects which
    		   can terminate the raw node refs' next_in_ino list -- which
    		   currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */
    
    		struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
    			temporary lists of dirents, and later must be set to
    			NULL to mark the end of the raw_node_ref->next_in_ino
    			chain. */
    		struct jffs2_raw_node_ref *nodes;
    		uint8_t class;	/* It's used for identification */
    	
    		/* end of shared structure */
    	
    		uint8_t flags;
    		uint16_t state;
    		/* @ino: 文件在文件系统中唯一的索引结点号 */
    		uint32_t ino;
    		/* @next: 链表,连接管理每一个inode缓存节点 */
    		struct jffs2_inode_cache *next;
    #ifdef CONFIG_JFFS2_FS_XATTR
    		struct jffs2_xattr_ref *xref;
    #endif
    		/* @pino_nlink: 如果是目录,则存储上级目录的inode号,否则存储链接个数,
    		 *     0表示没有链接 */
    		uint32_t pino_nlink;
    };
    

    5)struct jffs2_unknown_node

    所有jffs2节点的起始信息如下所示:(include/uapi/linux/jffs2.h

    struct jffs2_unknown_node
    {
    		/* @magic: 魔术位掩码,表明是否为jffs2文件系统 */
    		jint16_t magic; // JFFS2_MAGIC_BITMASK
    		/* @nodetype: 数据结点的具体类型,如: JFFS2_NODETYPE_DIRENT... */
    		jint16_t nodetype;
    		jint32_t totlen; /* So we can skip over nodes we don't grok */
    		/* @hdr_crc: crc校验,具体从哪个开始计算呢??? */
    		jint32_t hdr_crc;
    };
    

    6)struct jffs2_raw_dirent

    一个文件是由若干jffs2_raw_dirent或者jffs2_raw_inode数据实体组成。(include/uapi/linux/jffs2.h

    struct jffs2_raw_dirent
    {
    		jint16_t magic;
    		jint16_t nodetype;	/* == JFFS2_NODETYPE_DIRENT */
    		jint32_t totlen;
    		jint32_t hdr_crc;
    
    		/* @pino: 存放该文件的目录的索引结点号,用于表明自己所属的目录文件 */
    		jint32_t pino;
    		/* @version: 版本号是相对于某一文件内部的概念,当向文件某个区域写入新的数据时,
    		 *     它的版本号就会不断递增。一个文件的所有数据实体的最高版本号由
    		 *     @jffs2_inode_info中highest_version字段记录。 */
    		jint32_t version;
    		/* @ino: 文件的索引结点号 */
    		jint32_t ino; /* == zero for unlink */
    		jint32_t mctime;
    		__u8 nsize;
    		__u8 type;
    		__u8 unused[2];
    		jint32_t node_crc;
    		jint32_t name_crc;
    		__u8 name[0];
    };
    

    7)struct jffs2_raw_inode

    include/uapi/linux/jffs2.h

    struct jffs2_raw_inode
    {
    		jint16_t magic;      /* A constant magic number.  */
    		jint16_t nodetype;   /* == JFFS2_NODETYPE_INODE */
    		jint32_t totlen;     /* Total length of this node (inc data, etc.) */
    		jint32_t hdr_crc;
    		jint32_t ino;        /* Inode number.  */
    		jint32_t version;    /* Version number.  */
    		jmode_t mode;       /* The file's type or mode.  */
    		jint16_t uid;        /* The file's owner.  */
    		jint16_t gid;        /* The file's group.  */
    		jint32_t isize;      /* Total resultant size of this inode (used for truncations)  */
    		jint32_t atime;      /* Last access time.  */
    		jint32_t mtime;      /* Last modification time.  */
    		jint32_t ctime;      /* Change time.  */
    		/* @offset: 文件内部的偏移,该jffs2_raw_inode在flash分区中的偏移由内核描述符
    		 *     jffs2_raw_node_ref中flash_offset字段表示 */
    		jint32_t offset;
    		/* @csize: 压缩后的数据长度 */
    		jint32_t csize;
    		/* @dsize: 解压后的数据长度 */
    		jint32_t dsize;
    		__u8 compr;       /* Compression algorithm used */
    		__u8 usercompr;   /* Compression algorithm requested by the user */
    		jint16_t flags;	     /* See JFFS2_INO_FLAG_* */
    		jint32_t data_crc;   /* CRC for the (compressed) data.  */
    		jint32_t node_crc;   /* CRC for the raw inode (excluding data)  */
    		__u8 data[0];
    };
    

    8)struct jffs2_full_dirent

    struct jffs2_full_dirent
    {
    		union {
    				struct jffs2_raw_node_ref *raw;
    				struct jffs2_inode_cache *ic; /* Just during part of build */
    		};
    		struct jffs2_full_dirent *next;
    		uint32_t version;
    		uint32_t ino; /* == zero for unlink */
    		unsigned int nhash;
    		unsigned char type;
    		unsigned char name[0];
    };
    

    9)struct jffs2_node_frag

    struct jffs2_node_frag
    {
    		/* @rb: 用于组织红黑树,目的??? */
    		struct rb_node rb;
    		struct jffs2_full_dnode *node; /* NULL for holes */
    		/* @size, @ofs: 从jffs2_full_dnode中复制而来,表示数据结点所代表的区域在
    		 *     文件内的偏移和长度。 */
    		uint32_t size;
    		uint32_t ofs; /* The offset to which this fragment belongs */
    };
    

    10)struct jffs2_full_dnode

    struct jffs2_full_dnode
    {
    		struct jffs2_raw_node_ref *raw;
    		uint32_t ofs; /* The offset to which the data of this node belongs */
    		uint32_t size;
    		uint32_t frags; /* Number of fragments which currently refer
    				to this node. When this reaches zero,
    				the node is obsolete.  */
    };
    

    8)struct jffs2_eraseblock

    该结构体称为擦除块描述符,用于描述flash某个擦除块的信息。所有擦除块的描述符都存放载blocks[]中。另外,根据擦除块的状态,如是否由数据、数据是否过时等情况,还会将擦除块描述符组织在不同的链表中,以供文件系统的读写和 GC 使用(fs/jffs2/nodelist.h

    struct jffs2_eraseblock
    {
    		struct list_head list;
    		int bad_count;
    		uint32_t offset;		/* of this block in the MTD */
    	
    		uint32_t unchecked_size;
    		/* @used_size: 表示当前擦除块内有效数实体的空间大小 */
    		uint32_t used_size;
    		/* @dirty_size: 表示当前擦除块内过时数实体的空间大小 */
    		uint32_t dirty_size;
    		/* @wasted_size: 表示当前擦除块内无法利用的空间大小,由于flash数据
    		 *     结点必须4字节地址对齐导致。 */
    		uint32_t wasted_size;
    		/* @free_size: 表示当前擦除块内剩余空间大小 */
    		uint32_t free_size;	/* Note that sector_size - free_size
    					   is the address of the first free space */
    		uint32_t allocated_refs;
    		struct jffs2_raw_node_ref *first_node;
    		struct jffs2_raw_node_ref *last_node;
    	
    		struct jffs2_raw_node_ref *gc_node;	/* Next node to be garbage collected */
    };
    

    3、其它数据结构

    1)struct super_block

    VFS 描述文件系统使用超级块和inode的方式,所谓超级块就是对所有文件系统的管理机构,每种文件系统都要把自己的信息挂到super_blocks这么一个全局链表上。因此,每个super_blocks结构体可以代表一个文件系统。

    struct super_block {
    	/* @s_list: 双向链表,连接linux上所有文件系统对应的super_block */
    	struct list_head	s_list;		/* Keep this first */
    	dev_t				s_dev;		/* search index; _not_ kdev_t */
    	...
    } __randomize_layout;
    

    附录


    1、JFF2疑问

    Q1:为什么JFF2文件系统在挂载的时候需要遍历整个flash分区?
    A1: JFF2是一种日志型文件系统,该文件系统下的一个文件所有的数据实体可能分布在flash的任何位置上,每个文件对应若干jffs2_raw_inode结点,每个结点都各自描述自己的后继数据。正因为缺少类似ext2_inode的“索引”机制,所以在挂载jffs2时不得不白哪里整个flash分区,从而找到每个文件的所有数据实体,并建立它们的内核描述符jffs2_raw_node_ref并组织到文件的jffs2_inode_cache所在的nodes链表中。

    2、参考资料

    1. 以上源码内容参考自:Linux-4.15.18
    展开全文
  • 1、背景介绍最近为了使用PCIe驱动,对Linux内核进行了升级,目前ZYNQ发布的最新版内核为2017.4(对应内核版本4.9),升级虽然解决了PCIe驱动问题,但却引入了另一个奇怪的问题-挂载JFFS2文件系统时会出现如下错误:...
  •  我们在调试硬件板时,经常需要做多个jffs2的根文件系统映像,有时也要对比其他途径得到的可用的jffs2根文件系统映像。但jffs2的文件系统映像不象光盘的映像文件一样可以通过loop设备来挂载…… 我们在调试硬件板...
  • JFFS2创建文件过程

    2020-05-31 22:47:33
    JFFS2文件系统创建文件的过程,主要是通过VFS层的vfs_create()函数调用到jffs2_create()函数,由jffs2_create()函数负责文件的创建。 jffs2_create()函数具体创建文件的步骤是: 1.通过jffs2_new_inode()函数分配...
  • 不过直接用 `mount -t jffs2 -o loop' 挂载 JFFS2 镜像是不行的, 因为 `/dev/loop#' 不是一个 MTD 设备. 这儿就要用到 block2mtd 这个内核模块了. 在 mtd-utils 里边有 mkfs.jffs2jffs2dump. 那个 mkfs.jffs2 ...
  • JFFS2 及其新特性

    2016-02-05 11:46:58
    JFFS2 的必要性,然后详细的阐述了 JFFS2 实现的内部机制,包括日志结构的文件系统,关键的数据结构,挂载过程和垃圾收集机制。同时也指出了 JFFS2 的局限性,并介绍了最新的针对 JFFS2 的不足进行改进的补丁程
  • 从这篇博文开始,从代码角度梳理一下jffs2文件系统挂载的过程,整个过程主要以代码注释的形式呈现。本文内容基于linux4.4.198.请结合另一篇博客所述结构体进行阅读。 入口函数:jffs2_mount jffs2_mount只是简单的...
  • jffs2挂载问题

    2020-05-28 23:32:56
    制作根文件系统的JFFS2镜像。使用MTD工具中的mkfs.jffs2命令,具体做法如下: mkfs.jffs2 -r /home/tekkamanninja/working/nfs/rootfs -o rootfs.jffs2 -e 0x4000 --pad=0x500000 -s 0x200 -n
  • 如果要以挂载JFFS2格式的根文件系统,其基本方法就是将这个建立好的根文件系统制作成jffs2镜像,烧到FLASH中,改改Linux的启动参数即可。 具体做法如下:一、宿主机HOST编译制做MTD工具 从...
  • 文档详细描述了在linux下如何制作基于nerflash的jffs2文件系统的详细流程。
  • JFFS2是Flash上应用最广的一个日志结构文件系统。它提供的垃圾回收机制,不需要马上对擦写越界的块进行擦写,而只需要将其设置一个标志,标明为脏块,当可用的块数不足时,垃圾回收机制才开始回收这些节点。同时,...
  • 常见的文件系统有统的格式有:jffs2,yaffs2,ubifs等。但可基于存储或者运行的位置可分为 flash型文件系统,Ram型文件系统,网络文件系统 Flash型文件系统: Flash因为其特殊的硬件结构,普通的文件系统如ext2,...
  • Linux下的flash文件系统的性能比较,jffs2,yaffs2,ubifs
  • JFFS2文件系统(1)

    2020-03-08 22:24:57
    本文内容基于linux4.4.198. 最近用了下jffs2文件系统,把心得记录一下。 本文将从实用性的角度介绍jffs2文件系统,关于理论及介绍性的文章,网络上已经有很多了,可以结合着看,从不同角度一起梳理一下jffs2文件...
  • mkfs.jffs2命令

    2015-11-11 11:55:05
    Linux使用mkfs.jffs2命令需要安装mtd-utils工具 root@ubuntu:~# apt-get install mtd-utils root@ubuntu:~# mkfs.jffs2 --help mkfs.jffs2: error!: Usage: mkfs.jffs2 [OPTIONS] Make a JFFS2 file system ...
  • 一、根文件系统简介 根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于...根文件系统包括了Linux启动时所必须的目录和关键性的文件,例如Linux启动时都需要有init目...
1 2 3 4 5 ... 20
收藏数 9,127
精华内容 3,650
热门标签