精华内容
下载资源
问答
  • JFFS2创建文件过程
    2020-04-12 22:49:25

    本文内容基于内核版本linux4.4.198.
    JFFS2文件系统创建文件的过程,主要是通过VFS层的vfs_create()函数调用到jffs2_create()函数,由jffs2_create()函数负责文件的创建。
    jffs2_create()函数具体创建文件的步骤是:
    1.通过jffs2_new_inode()函数分配inode结构体以及jffs2_inode_info、jffs2_inode_cache结构体,然后调用jffs2_do_create()函数依次向flash中写入inode和dirent节点。下面我们来看具体代码的实现。

    首先,jffs2_dir_inode_operations结构体中将jffs2_create赋给create钩子。

    const struct inode_operations jffs2_dir_inode_operations =
    {
    	.create =	jffs2_create,
    	.lookup =	jffs2_lookup,
    	.link =		jffs2_link,
    	.unlink =	jffs2_unlink,
    	.symlink =	jffs2_symlink,
    	.mkdir =	jffs2_mkdir,
    	.rmdir =	jffs2_rmdir,
    	.mknod =	jffs2_mknod,
    	.rename =	jffs2_rename,
    	.get_acl =	jffs2_get_acl,
    	.set_acl =	jffs2_set_acl,
    	.setattr =	jffs2_setattr,
    	.setxattr =	jffs2_setxattr,
    	.getxattr =	jffs2_getxattr,
    	.listxattr =	jffs2_listxattr,
    	.removexattr =	jffs2_removexattr
    };
    
    static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
    			umode_t mode, bool excl)
    {
    	struct jffs2_raw_inode *ri;
    	struct jffs2_inode_info *f, *dir_f;
    	struct jffs2_sb_info *c;
    	struct inode *inode;
    	int ret;
    
    	ri = jffs2_alloc_raw_inode(); //分配jffs2_raw_inode结构体
    	if (!ri)
    		return -ENOMEM;
    
    	c = JFFS2_SB_INFO(dir_i->i_sb);
    
    	jffs2_dbg(1, "%s()\n", __func__);
    
    	inode = jffs2_new_inode(dir_i, mode, ri);
    
    	if (IS_ERR(inode)) {
    		jffs2_dbg(1, "jffs2_new_inode() failed\n");
    		jffs2_free_raw_inode(ri);
    		return PTR_ERR(inode);
    	}
    
    //inode结构体相应成员赋值
    	inode->i_op = &jffs2_file_inode_operations;
    	inode->i_fop = &jffs2_file_operations;
    	inode->i_mapping->a_ops = &jffs2_file_address_operations;
    	inode->i_mapping->nrpages = 0;
    
    	f = JFFS2_INODE_INFO(inode); //获取jffs2_inode_info结构体
    	dir_f = JFFS2_INODE_INFO(dir_i);
    
    	/* jffs2_do_create() will want to lock it, _after_ reserving
    	   space and taking c-alloc_sem. If we keep it locked here,
    	   lockdep gets unhappy (although it's a false positive;
    	   nothing else will be looking at this inode yet so there's
    	   no chance of AB-BA deadlock involving its f->sem). */
    	mutex_unlock(&f->sem);
    
    	ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name); //主要的工作在这里完成
    	if (ret)
    		goto fail;
    
    	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
    
    	jffs2_free_raw_inode(ri); //释放内存
    
    	jffs2_dbg(1, "%s(): Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
    		  __func__, inode->i_ino, inode->i_mode, inode->i_nlink,
    		  f->inocache->pino_nlink, inode->i_mapping->nrpages);
    
    	d_instantiate_new(dentry, inode); //将dentry与inode关联
    	return 0;
    
     fail:
    	iget_failed(inode);
    	jffs2_free_raw_inode(ri);
    	return ret;
    }
    

    先分析jffs2_new_inode()函数。
    这个函数主要是对相关结构体成员进行赋值,还把一部分工作委托给jffs2_do_new_inode()函数。

    /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
       fill in the raw_inode while you're at it. */
    struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri)
    {
    	struct inode *inode;
    	struct super_block *sb = dir_i->i_sb;
    	struct jffs2_sb_info *c;
    	struct jffs2_inode_info *f;
    	int ret;
    
    	jffs2_dbg(1, "%s(): dir_i %ld, mode 0x%x\n",
    		  __func__, dir_i->i_ino, mode);
    
    	c = JFFS2_SB_INFO(sb);
    
    	inode = new_inode(sb); //这个函数会调用sb相关分配inode的回调函数jffs2_alloc_inode
    
    	if (!inode)
    		return ERR_PTR(-ENOMEM);
    
    	f = JFFS2_INODE_INFO(inode);
    	jffs2_init_inode_info(f); //初始化jffs2_inode_info
    	mutex_lock(&f->sem);
    
    	memset(ri, 0, sizeof(*ri)); //初始化传入的jffs2_raw_inode
    	/* Set OS-specific defaults for new inodes */
    	ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid()));
    
    	if (dir_i->i_mode & S_ISGID) {
    		ri->gid = cpu_to_je16(i_gid_read(dir_i));
    		if (S_ISDIR(mode))
    			mode |= S_ISGID;
    	} else {
    		ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid()));
    	}
    
    	/* POSIX ACLs have to be processed now, at least partly.
    	   The umask is only applied if there's no default ACL */
    	ret = jffs2_init_acl_pre(dir_i, inode, &mode); //初始化ACL
    	if (ret) {
    		mutex_unlock(&f->sem);
    		make_bad_inode(inode);
    		iput(inode);
    		return ERR_PTR(ret);
    	}
    	ret = jffs2_do_new_inode (c, f, mode, ri); //完成分配和初始化jffs2_inode_cache的任务,jffs2_inode_cache会被加入到sb的hash表中
    	if (ret) {
    		mutex_unlock(&f->sem);
    		make_bad_inode(inode);
    		iput(inode);
    		return ERR_PTR(ret);
    	}
    	//下面对inode结构体相关成员进行初始化
    	set_nlink(inode, 1);
    	inode->i_ino = je32_to_cpu(ri->ino);
    	inode->i_mode = jemode_to_cpu(ri->mode);
    	i_gid_write(inode, je16_to_cpu(ri->gid));
    	i_uid_write(inode, je16_to_cpu(ri->uid));
    	inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
    	ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
    
    	inode->i_blocks = 0;
    	inode->i_size = 0;
    
    	if (insert_inode_locked(inode) < 0) { //最后把inode加入inode的hash表中,这里和VFS相关
    		mutex_unlock(&f->sem);
    		make_bad_inode(inode);
    		iput(inode);
    		return ERR_PTR(-EINVAL);
    	}
    
    	return inode;
    }
    
    int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
    		       uint32_t mode, struct jffs2_raw_inode *ri)
    {
    	struct jffs2_inode_cache *ic;
    
    	ic = jffs2_alloc_inode_cache(); //分配jffs2_inode_cache
    	if (!ic) {
    		return -ENOMEM;
    	}
    //下面都是对jffs2_inode_cache相关的初始化
    	memset(ic, 0, sizeof(*ic));
    
    	f->inocache = ic;
    	f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
    	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
    	f->inocache->state = INO_STATE_PRESENT;
    
    	jffs2_add_ino_cache(c, f->inocache);
    	jffs2_dbg(1, "%s(): Assigned ino# %d\n", __func__, f->inocache->ino);
    	ri->ino = cpu_to_je32(f->inocache->ino);
    
    	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
    	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
    	ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
    	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
    	ri->mode = cpu_to_jemode(mode);
    
    	f->highest_version = 1;
    	ri->version = cpu_to_je32(f->highest_version);
    
    	return 0;
    }
    

    接下来分析jffs2_do_create()函数。这个函数根据传入的信息,依次将raw_inode和raw_dirent节点写入flash中。

    int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
    		    struct jffs2_inode_info *f, struct jffs2_raw_inode *ri,
    		    const struct qstr *qstr)
    {
    	struct jffs2_raw_dirent *rd;
    	struct jffs2_full_dnode *fn;
    	struct jffs2_full_dirent *fd;
    	uint32_t alloclen;
    	int ret;
    
    	/* Try to reserve enough space for both node and dirent.
    	 * Just the node will do for now, though
    	 */
    	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
    				JFFS2_SUMMARY_INODE_SIZE); //下入前都要调用这个函数留出足够空间
    	jffs2_dbg(1, "%s(): reserved 0x%x bytes\n", __func__, alloclen);
    	if (ret)
    		return ret;
    
    	mutex_lock(&f->sem); //写操作要获取jffs2_inode_info的sem锁
    
    //初始化要写入的jffs2_raw_inode的各个成员
    //因为是create操作,所以只写入一个空inode
    	ri->data_crc = cpu_to_je32(0);
    	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
    
    	fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); //将inode节点写入flash
    
    	jffs2_dbg(1, "jffs2_do_create created file with mode 0x%x\n",
    		  jemode_to_cpu(ri->mode));
    
    	if (IS_ERR(fn)) {
    		jffs2_dbg(1, "jffs2_write_dnode() failed\n");
    		/* Eeek. Wave bye bye */
    		mutex_unlock(&f->sem);
    		jffs2_complete_reservation(c);
    		return PTR_ERR(fn);
    	}
    	/* No data here. Only a metadata node, which will be
    	   obsoleted by the first data write
    	*/
    	f->metadata = fn; //此时该文件只有一个空inode节点,所以将metadata指向fn
    
    	mutex_unlock(&f->sem); //这里先释放锁
    	jffs2_complete_reservation(c);//调用jffs2_reserve_space后都要调用这个函数
    
    	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);
    	if (ret)
    		return ret;
    	ret = jffs2_init_acl_post(&f->vfs_inode);
    	if (ret)
    		return ret;
    
    	ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen,
    				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len)); //为写入raw_dirent腾出空间
    
    	if (ret) {
    		/* Eep. */
    		jffs2_dbg(1, "jffs2_reserve_space() for dirent failed\n");
    		return ret;
    	}
    
    	rd = jffs2_alloc_raw_dirent(); //分配内存空间,写入完成后会释放
    	if (!rd) {
    		/* Argh. Now we treat it like a normal delete */
    		jffs2_complete_reservation(c);
    		return -ENOMEM;
    	}
    
    	mutex_lock(&dir_f->sem); //注意,写dirent获取的锁与上面写inode获取的锁不一样
    //初始化raw_dirent的相关成员
    	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
    	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
    	rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len);
    	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
    
    	rd->pino = cpu_to_je32(dir_f->inocache->ino);
    	rd->version = cpu_to_je32(++dir_f->highest_version);
    	rd->ino = ri->ino;
    	rd->mctime = ri->ctime;
    	rd->nsize = qstr->len;
    	rd->type = DT_REG;
    	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
    	rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len));
    
    	fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL); //完成写入操作
    
    	jffs2_free_raw_dirent(rd); //释放内存
    
    	if (IS_ERR(fd)) {
    		/* dirent failed to write. Delete the inode normally
    		   as if it were the final unlink() */
    		jffs2_complete_reservation(c);
    		mutex_unlock(&dir_f->sem);
    		return PTR_ERR(fd);
    	}
    
    	/* Link the fd into the inode's list, obsoleting an old
    	   one if necessary. */
    	jffs2_add_fd_to_list(c, fd, &dir_f->dents);//将full_dirent加入dents链表
    
    	jffs2_complete_reservation(c);
    	mutex_unlock(&dir_f->sem);
    
    	return 0;
    }
    

    至此,jffs2创建新文件的操作就分析完了。
    创建文件后,接下来就是往文件里写数据了,具体流程在下一篇分析。这里先提个问题,JFFS2是支持数据压缩的文件系统,且jffs2的节点不会跨越块,那么,如果本次写的数据大于本块剩余空间大小,那怎么办?
    答案是,看jffs2_compress()函数的注释,在调用jffs2_write_inode_range()之前会调用前者,前者确保空间被充分利用。

    更多相关内容
  • XILINX zynq系统的petalinux工程挂载jffs2文件系统的petalinux配置工作流程,已成功应用下载到目标板卡,板卡重新启动所建立的文件夹和文件不会丢失。
  • 包含机器的主要mtd分区以及完整的jffs2和地区包备份,可用于救砖 制作固件
  • 本文主要介绍如何在AT91SAM9261EK板子上制作和使用jffs2文件系统,使用的是linux-2.6.21内核。
  • 适配于Tiny6410的根文件系统的.jffs2文件,已测试,和yaffs2文件系统差不多,只不过jffs2是压缩的文件系统,比yaffs2文件系统差不多小一半。
  • 华为光猫HS8145V的jffs备份,需要恢复电信界面可以使用。
  • 文章以SST39VF160芯片为例,讨论了在Nor Flash上建立uClinux的JFFS2文件系统的一般步骤,从而为FLASH上的数据管理提供了理想的选择方式。 关键词:uClinux;Nor Flash;MTD;JFFS2;文件系统嵌入式系统正随着...
  •  JFFS2是Flash上应用最广的一个日志结构文件系统。它提供的垃圾回收机制,不需要马上对擦写越界的块进行擦写,而只需要将其设置一个标志,标明为脏块,当可用的块数不足时,垃圾回收机制才开始回收这些节点。同时,...
  • jffs2文件系统工具

    2016-10-21 16:20:53
    jffs2文件系统工具
  • jffs2文件系统(完整)

    2014-08-31 18:13:15
    制作步骤: (1)配置内核支持jffs2文件系统。 File systems ---> [*] Miscellaneous filesystems ---> <*> Journalling Flash ... $ mkfs.jffs2 -r /source/rootfs -o rootfs.jffs2 -e 0x20000 --pad=0x400000 -n
  • jffs2.img二进制文件

    2021-04-01 10:33:17
    荔枝派Zero(V3s)制作SPI Flash 系统镜像时使用的最小根文件系统二进制文件
  • 嵌入式LINUX下的JFFS2文件系统实现.pdf
  • 共享给大家看看, 主要是手上没有信元了, 分析 JFFS2文件系统源代码情景分析.rar 134.19 KB, 下载次数: 124 , 下载积分: 资产 -2 信元, 下载支出 2 信元 JFFS2文件系统源代码情景分析.rar
  • JFFS和YAFFS两种文件系统在嵌入式Linux平台上的运行比较.pdf
  • 基于JFFS2文件系统的终端升级方案,邓继洲,陈伟,本文实现了基于JFFS2文件系统的电力负控管理终端升级方案。由于程序的更新换代,终端设备的升级必不可少。由于电力负控管理终端使�
  • mkfs.jffs2

    2014-08-22 09:11:31
    本资源包括jffs2文件系统源代码及相关依赖库源代码,具体编译、安装步骤的详细说明。
  • JFFS2

    千次阅读 2019-04-24 08:02:47
    文章目录一、JFFS2介绍1、JFFS2简介2、JFFS2框架二、JFFS2实现1、JFFS2的机制2、JFFS2数据结构1)struct jffs2_sb_info3、其它数据结构1)struct super_block附录1、参考资料 一、JFFS2介绍 1、JFFS2简介 2、JFFS2...

    一、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
    展开全文
  • 制作jffs2文件系统

    2021-05-15 23:39:55
    文件:zlib-1.2.3.tar.gz大小:484KB下载:文件:mtd-snapshot-20050519.tar.bz2大小:1227KB下载:制作mtd-util工具:从网上下载zlib-1.2.3.tar.gzzlib-1.2.3.tar.gz下载需要先登录...jffs2的源代码MTD TOOLS生成成功!h...

    zip.gif

    文件:

    zlib-1.2.3.tar.gz

    大小:

    484KB

    下载:

    zip.gif

    文件:

    mtd-snapshot-20050519.tar.bz2

    大小:

    1227KB

    下载:制作mtd-util工具:从网上下载zlib-1.2.3.tar.gz

    zlib-1.2.3.tar.gz下载需要先登录

    从网上下载 mtd-snapshot-20050519.tar.bz2

    下可以下载到 jffs2的源代码

    MTD TOOLS生成成功!

    http://blog.csdn.net/hongjiujing/archive/2007/09/21/1794530.aspx

    有关jffs2文件系统的问题

    在pc端制作文件系统,通过uboot烧写到开发板,可参考:

    在nand flash上实现JFFS2根文件文件系统

    http://www.mcuol.com/Tech/216/28699.htm

    基本操作摘抄如下:

    1.下载MTD工具包

    farsight#tar –jxvf mtd-snapshot-20050519.tar.bz2

    farsight#cd mtd

    farsight#./configure  解压后没有该文件,不知作者怎么做此操作??

    farsight#make

    farsight#make install

    如果系统中没有安装ZLIB库,那么首先安装ZLIB库。具体的安装过程如下:

    farsight#tar –zxvf zlib-1.2.3.tar.gz

    farsight#cd zlib-1.2.3

    farsight#./configure

    farsight#make

    farsight#make install

    完成此步骤后,系统中就有了mkfs.jffs2的工具。

    2、制作JFFS2文件镜像

    farsight#mkfs.jffs2 -r /source/rootfs -o rootfs.jffs2 -e 0x4000 --pad=0x800000 -n

    这样就会生成一个8M大小的rootfs.jffs2的镜像,它也正是JFFS2文件系统的镜像,关于这个命令行里的选项的内容,可以用man a mkfs.jffs2命令来查看内容。

    3、设置内核启动参数   本处用的bootloader是U-BOOT.所以在U-BOOT的命令终端设置如下:

    FS2410#setenv bootargs root=/dev/mtdblock/2 rootfstype=jffs2 rw console=ttySAC0,115200 init=/linuxrc mem=64M

    4、配置内核支持JFFS2文件系统

    File systems ---> Miscellaneous filesystems --->

    JournallingFlash File System v2 (JFFS2) support

    [*]JFFS2write-bufferingsupport

    [*]AdvancedcompressionoptionsforJFFS2

    [*]JFFS2ZLIBcompressionsupport

    [*]JFFS2RTIMEcompressionsuppor

    [*] JFFS2 RUBIN compression support

    5、下载rootfs.jffs2镜像

    下载到Nand Flash第二个分区。

    FS2410#nand erase 200000 800000

    FS2410#nand write.jffs2 300008000 200000 800000

    主要步骤:

    用arm-linux-gcc编译:zlib-1.2.3.tar.gz, mtd-snapshot-20050519.tar.bz2 最后生成在开发板上可以使用的flash_erase,flash_eraseall, mkfs.jffs2工具放在ramdisk 文件系统中,同时复制用到的库文件libz.so, libz.so.1, libz.so.1.2.3;

    擦除nandflash

    # flash_erase /dev/mtd1

    制作jffs2映像

    # cd /var/tmp

    # mkdir jffs2 (jffs2下的目录可以任意建)

    # mkfs.jffs2 –d jffs2/ -o jffs2.img

    # cp /var/tmp/jffs2/jffs2.img /dev/mtdblock1

    最后# mount -t jffs2 /dev/mtdblock1 /mnt/mtd即可。

    如果只是当作普通的jffs2 来使用dataflash或者nandflash,可不必制作 jffs2映像,只需要最后一步

    # mount -t jffs2 /dev/mtdblock1 /mnt/mtd即可。

    实现过程中遇到的ECC的问题:

    1.把make menuconfig中的

    Device Drivers --->

    Memory Technology Devices (MTD) --->

    NAND Flash Kevice Drivers--->

    [*] S3C2410 NAND Hardware ECC

    选中后,系统不能正常启动;

    2.要把  drivers/mtd/nand/s3c2410.c 的ecc校验:

    chip->eccmod = NAND_ECC_SOFT改为:

    chip->eccmod = NAND_ECC_NONE

    则每次启动时提示:Reading data from NAND FLASH without ECC is not recommended

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e154: 0xfbeb instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e154: 0xfbeb instead

    Further such events for this erase block will not be printed

    Empty flash at 0x0050e280 ends at 0x0050e284

    Empty flash at 0x0050e2d4 ends at 0x0050e2d8

    Reading data from NAND FLASH without ECC is not recommended

    VFS:Mounted root (jffs2 filesystem).

    Mounted devfs on /dev

    Freeing init memory:92K

    Reading data from NAND FLASH without ECC is not recommended

    Reading data from NAND FLASH without ECC is not recommended

    starting pid 17,tty '': '/etc/init.d/rcS'

    Cannot run '/etc/init.d/rcS': No such file or directory

    Reading data from NAND FLASH without ECC is not recommended

    jffs2_get_inode_nodes(): Data CRC failed on node at 0x0068d888: Read 0xf0b01ebl, calculated 0xfd24ef86

    jffs2_get_inode_nodes(): Data CRC failed on node at 0x0050f2c4: Read 0x18e8b547, calculated 0xcdd71ab0

    jffs2_get_inode_nodes(): CRC failed on node at 0x0068e9d4: Read 0xffffffff, calculated 0xb4c178b1

    starting pid 18, Reding data from NAND FLASH without ECC is not recommended

    tty '': '/bin/sh'

    每次执行命令时会提示:

    Reading data from NAND FLASH without ECC is not recommended

    Writing data without ECC to NAND-FLASH is not recommended

    3.不选择[] S3C2410 NAND Hardware ECC;且chip->eccmod = NAND_ECC_SOFT保持不变,则启动时会提示,但进入提示符操作没有问题。

    Root-NFS: No NFS server available, giving up.

    VFS: Unable to mount root fs via NFS, trying floppy.

    mtd->read(0x3c0c bytes from 0x50c3f4) returned ECC error

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e154: 0xfbeb instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e158: 0xffcf instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e15c: 0xfee9 instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e160: 0xeeff instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e164: 0xfffb instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e168: 0xfdef instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e16c: 0xffff instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e170: 0x9ffd instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e174: 0x79ff instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e178: 0xfdff instead

    Further such events for this erase block will not be printed

    Empty flash at 0x0050e280 ends at 0x0050e284

    Empty flash at 0x0050e2d4 ends at 0x0050e2d8

    Empty flash at 0x0050e424 ends at 0x0050e428

    Empty flash at 0x0050e530 ends at 0x0050e534

    Empty flash at 0x0050e56c ends at 0x0050e570

    Empty flash at 0x0050e604 ends at 0x0050e608

    Empty flash at 0x0050e668 ends at 0x0050e66c

    Empty flash at 0x0050e714 ends at 0x0050e718

    Empty flash at 0x0050e728 ends at 0x0050e72c

    Empty flash at 0x0050e7e8 ends at 0x0050e7ec

    Empty flash at 0x0050e7f0 ends at 0x0050e7f4

    Empty flash at 0x0050fb58 ends at 0x0050fc00

    mtd->read(0x400 bytes from 0x68c000) returned ECC error

    mtd->read(0x397c bytes from 0x68c684) returned ECC error

    Empty flash at 0x0068de88 ends at 0x0068e000

    Empty flash at 0x0068ea28 ends at 0x0068ec00

    jffs2_scan_eraseblock(): Node at 0x0068ee58 {0x1985, 0xa002, 0x00000081) has invalid CRC 0xd964e529 (calculated 0x8197bd60)

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee5c: 0x0081 instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee60: 0xe529 instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee64: 0x023f instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee68: 0x0026 instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee6c: 0x81a4 instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee74: 0x004a instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee78: 0x00ed instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee7c: 0x00ed instead

    jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0068ee80: 0x00ed instead

    Further such events for this erase block will not be printed

    VFS: Mounted root (jffs2 filesystem).

    Mounted devfs on /dev

    Freeing init memory: 92K

    init started: BusyBox v1.7.3 (2008-08-20 09:39:18 CST)

    starting pid 17, tty '': '/etc/init.d/rcS'

    Cannot run '/etc/init.d/rcS': No such file or directory

    Please press Enter to activate this console. mtd->read(0x44 bytes from 0x68d888) returned ECC error

    展开全文
  • 出现打印如下: jffs2: Empty flash at 0x0000a808 ends at 0x0000b000 出现很多 jffs2: notice: (463) check_node_data: wrong data CRC in data node at 0x000dcf04: read 0x1eab68d7, calculated 0xe934f4ac....
  • 本 文介绍了3种源码开放的嵌入式文件系统Cramfs、JFFS2、YAFFS2,详细分析比较了这3种文件系统的主要性能,并根据分析结果指出了各自的适 用领域 Cramfs、JFFS2、YAFFS2是3种性能优越,专用于嵌入式系统的文件系统...
  •   JFFS2的全名为JournallingFlashFileSystemVersion2(闪存日志型文件系统第2版),其功能就是管理在MTD设备上实现的日志型文件系统。与其他的存储设备存储方案相比,JFFS2并不准备提供让传统文件系统也可以使用...

    前言

      JFFS2的全名为JournallingFlashFileSystemVersion2(闪存日志型文件系统第2版),其功能就是管理在MTD设备上实现的日志型文件系统。与其他的存储设备存储方案相比,JFFS2并不准备提供让传统文件系统也可以使用此类设备的转换层。它只会直接在MTD设备上实现日志结构的文件系统。JFFS2会在安装的时候,扫描MTD设备的日志内容,并在RAM中重新建立文件系统结构本身。
      除了提供具有断电可靠性的日志结构文件系统,JFFS2还会在它管理的MTD设备上实现“损耗平衡”和“数据压缩”等特性。
      很强大很好用但是最近调试还是遇见了一些错误,先记录2个,以后遇见了再补充:

    错误类型一:使用一段时间后崩溃无法启动

      这是个遇见了很奇怪的现象,文件系统在使用了一段时间后崩溃需要擦除后再次重新烧写,而且使用时间似乎和使用次数无关,感觉不太符合常理:
      下面是一次关于jffs2部分无法加载的错误日志:

    GKHY___________________________________________________TEST
    NET: Registered protocol family 29
    can: raw protocol (rev 20170425)
    can: broadcast manager protocol (rev 20170425 t)
    can: netlink gateway (rev 20170425) max_hops=1
    Registering SWP/SWPB emulation handler
    hctosys: unable to open rtc device (rtc0)
    of_cfs_init
    of_cfs_init: OK
    ALSA device list:
    ▒random: crng init done
    jffs2: error: (1) jffs2_link_node_ref: Adding new ref ef185ba8 at (0x00700000-0x007002d0) not immediately after previous (0x00700000-0x00700000)
    Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
    Modules linked in:
    CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.14.0-xilinx #1
    Hardware name: Xilinx Zynq Platform
    task: ef058000 task.stack: ef04e000
    PC is at jffs2_link_node_ref+0x20/0x180
    LR is at jffs2_link_node_ref+0x158/0x180
    pc : [<c02b089c>]    lr : [<c02b09d4>]    psr: 60000113
    sp : ef04fcc8  ip : 00000000  fp : ef029ff8
    r10: c0a52f84  r9 : 0000e002  r8 : 00000000
    r7 : ef248000  r6 : ef02d5b0  r5 : 000002d0  r4 : ef185ba8
    r3 : 00000000  r2 : 00000000  r1 : 2ee98000  r0 : 00000090
    Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
    Control: 18c5387d  Table: 0000404a  DAC: 00000051
    Process swapper/0 (pid: 1, stack limit = 0xef04e210)
    Stack: (0xef04fcc8 to 0xef050000)
    fcc0:                   00700000 007002d0 00700000 00700000 ef286000 ef02d5b0
    fce0: ef248032 c02bcc38 ef2b04e0 c03f3350 00004f7c 00000000 00004f84 00000000
    fd00: 00004f84 00040000 00000008 20061985 00004f84 00000000 ef029ff8 ef286000
    fd20: ef02d5b0 00004f84 00000008 ef248000 ef029000 00000000 ef029ff8 c02b50ec
    fd40: c0a52f84 ef04fd84 ef04fd80 00000000 c0a3c7c8 00001000 006ff160 ee9cf900
    fd60: 000005b0 ef02d000 00000000 00700000 00000000 00000000 0000001c 006c0000
    fd80: ef029000 00000000 00001000 e0021985 0000024b c02ba0dc ef286000 ef286000
    fda0: 00000000 ee97bc00 00a00000 c02ba0dc ee9cfc04 00000020 00008000 c02b7af0
    fdc0: c02ba0fc 00000000 00000594 00000020 00008000 00000000 ef001b40 ef286000
    fde0: 00040000 ee97bc00 00a00000 c02ba0dc ee9cfc04 00000020 00008000 c02b9c14
    fe00: ee97bc00 ee9c1000 00008000 00000000 c02ba0dc c03f4438 ee9c1000 00008000
    fe20: 00000000 ee9cfc00 00008000 c0a115d0 00000000 c03f451c c02ba0dc ee9d1c00
    fe40: c0a03e48 c0a501a8 ee9cfc00 c02b9dac 00008000 ee9cfc00 c0a115d0 00000000
    fe60: 00000000 c02b9dbc c02ba0dc 00008000 ee9cfc00 c01da218 ee9d1c00 c01f28dc
    fe80: c0a115d0 00008000 00000020 ee9cfc00 ee9cfe40 c01f5450 00000000 ee9cfc00
    fea0: c093486c 00000051 ef015110 eec08198 00000007 00000000 00000007 c01abd74
    fec0: 00000007 c07e3618 ee9cfe40 ee9cfc00 00000000 00008000 00008000 c093486c
    fee0: c07e3618 c01f58c0 00000000 c07e3618 ee9e2000 ee9e2000 efdcac40 c093485c
    ff00: efffcbbc c0901104 00000000 00000000 ef7cf300 c015e578 ee9cce00 c093485c
    ff20: c093485c c0a3d240 c0934838 000000e6 c0a3d240 c03bdf9c 00000000 c093485c
    ff40: c093486c c0934838 000000e6 c0a3d240 c093e2a8 c093483c 00000000 c09014d4
    ff60: fffffffe 00002710 00000009 c0a3d240 c0934838 c0900d84 00000007 00000007
    ff80: 00000000 c090059c 00000000 c0650654 00000000 00000000 00000000 00000000
    ffa0: 00000000 c065065c 00000000 c01070f0 00000000 00000000 00000000 00000000
    ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 80026000 10100041
    [<c02b089c>] (jffs2_link_node_ref) from [<c02bcc38>] (jffs2_sum_scan_sumnode+0x28c/0x4cc)
    [<c02bcc38>] (jffs2_sum_scan_sumnode) from [<c02b50ec>] (jffs2_scan_medium+0x400/0x1070)
    [<c02b50ec>] (jffs2_scan_medium) from [<c02b7af0>] (jffs2_do_mount_fs+0x170/0x608)
    [<c02b7af0>] (jffs2_do_mount_fs) from [<c02b9c14>] (jffs2_do_fill_super+0x164/0x20c)
    [<c02b9c14>] (jffs2_do_fill_super) from [<c03f4438>] (mount_mtd_aux.constprop.0+0x4c/0xac)
    [<c03f4438>] (mount_mtd_aux.constprop.0) from [<c03f451c>] (mount_mtd+0x84/0x138)
    [<c03f451c>] (mount_mtd) from [<c02b9dbc>] (jffs2_mount+0x10/0x1c)
    [<c02b9dbc>] (jffs2_mount) from [<c01da218>] (mount_fs+0xc/0x44)
    [<c01da218>] (mount_fs) from [<c01f28dc>] (vfs_kern_mount+0x4c/0xe8)
    [<c01f28dc>] (vfs_kern_mount) from [<c01f5450>] (do_mount+0x814/0xa44)
    [<c01f5450>] (do_mount) from [<c01f58c0>] (SyS_mount+0x70/0x98)
    [<c01f58c0>] (SyS_mount) from [<c0901104>] (mount_block_root+0x110/0x25c)
    [<c0901104>] (mount_block_root) from [<c09014d4>] (prepare_namespace+0x84/0x1b4)
    [<c09014d4>] (prepare_namespace) from [<c0900d84>] (kernel_init_freeable+0x168/0x1c8)
    [<c0900d84>] (kernel_init_freeable) from [<c065065c>] (kernel_init+0x8/0x108)
    [<c065065c>] (kernel_init) from [<c01070f0>] (ret_from_fork+0x14/0x24)
    Code: 124cc001 1581c024 1591402c 1a000003 (e7f001f2)
    ---[ end trace f7fa44ebf9c6f0ca ]---
    Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
    
    CPU0: stopping
    CPU: 0 PID: 0 Comm: swapper/0 Tainted: G      D         4.14.0-xilinx #1
    Hardware name: Xilinx Zynq Platform
    [<c010e894>] (unwind_backtrace) from [<c010aad0>] (show_stack+0x10/0x14)
    [<c010aad0>] (show_stack) from [<c063fb48>] (dump_stack+0x80/0xa0)
    [<c063fb48>] (dump_stack) from [<c010cff8>] (ipi_cpu_stop+0x3c/0x70)
    [<c010cff8>] (ipi_cpu_stop) from [<c010d818>] (handle_IPI+0x64/0x84)
    [<c010d818>] (handle_IPI) from [<c0101420>] (gic_handle_irq+0x84/0x90)
    [<c0101420>] (gic_handle_irq) from [<c010b50c>] (__irq_svc+0x6c/0xa8)
    Exception stack(0xc0a01f20 to 0xc0a01f68)
    1f20: 00000000 00000000 2ee88000 ef7ced00 a219b87f 00000000 ef7ce1c0 00000000
    1f40: 8b5cfccd 00000000 00000000 00000000 00000015 c0a01f70 c04e13e4 c04e1408
    1f60: 60000013 ffffffff
    [<c010b50c>] (__irq_svc) from [<c04e1408>] (cpuidle_enter_state+0xe4/0x1b4)
    [<c04e1408>] (cpuidle_enter_state) from [<c01494a8>] (do_idle+0x148/0x1a8)
    [<c01494a8>] (do_idle) from [<c0149640>] (cpu_startup_entry+0x18/0x1c)
    [<c0149640>] (cpu_startup_entry) from [<c0900bbc>] (start_kernel+0x304/0x364)
    [<c0900bbc>] (start_kernel) from [<0000807c>] (0x807c)
    ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
    

    解决办法:

      参考了https://bugzilla.redhat.com/show_bug.cgi?id=717635#c12中大佬们之间的交流,如果没有理解错误的话可能是因为summery support的问题
    在这里插入图片描述
      于是我也将这个选项取消了,但是需要很长时间才会检测出异常,短时间内也不知道这样的改法是否有效。(目前已稳定运行一个月)
      具体修改位置如下:
    在这里插入图片描述

    错误类型2:内核直接打印错误

    在启动日志中直接可以清晰地看到jffs2 error,具体内容如下:

    JFFS2 error: (1) jffs2_build_inode_pass1: child dir " dnf" (ino #1120) of dir ino #1074 appears to be a hard link 
    JFFS2 error: (1) jffs2_build_inode_pass1: child dir "l" (ino #1170) of dir ino #1075 appears to be a hard link 
    

    原因及解决办法

    : flash没有erase彻底. 在重新擦除后再次烧写文件系统就没有这样的问题了

    展开全文
  • JFFS2 源代码情景分析

    2013-10-24 11:05:11
    jffs2文件系统源代码分析,包括数据结构和相关函数
  • JFFS2文件系统(1)

    2020-01-31 22:53:44
    本文将从实用性的角度介绍jffs2文件系统,关于理论及介绍性的文章,网络上已经有很多了,可以结合着看,从不同角度一起梳理一下jffs2文件系统的相关内容。 直接上jffs2中重要的的数据结构和宏吧。 存放在flash上的...
  • jffs2 源代码情景分析

    2018-03-06 11:30:01
    关于jffs2源代码分析的一个文档,希望对有需要的人有用。
  • 描述了ARM-LINUX上JFFS2制作过程
  • 在介绍JFFS2文件系统基本结构的基础上,分析了其文件系统的装载过程,并对多种最新的改进策略进行了总结和研究。
  • NAND flash probing at 0x4E000000 64 MB In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 [Tekkaman2440]#nfs 0x30008000 192.168.1.22:/home/tekkamanninja/working/nfs/rootfs.jffs2 ...
  • mkfs.jffs2: Usage: mkfs.jffs2 [OPTIONS]Make a JFFS2 file system image from an existing directory treeOptions:-p, --pad[=SIZE]用16進制來表示所要輸出檔案的大小,也就是root.jffs2的size。很重要的是, 為了...
  • 首先为每个jffs2_inode_cache分配一个jffs2_inode_info结构体,然后将检查工作交给jffs2_do_read_inode_internal函数 int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { ...
  • mkfs.jffs2使用方法

    2021-05-15 22:31:19
    下载:或者使用命令:apt-get install mtd-utils命令使用实例:mkfs.jffs2 -s 0x1000 -e 0x40000 -p 0x500000 -d rootfs/ -o jffs2.img说明:页大小0x1000 4k块大小0x40000 256kjffs2分区总空间0x500000即5M当然生成...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,836
精华内容 5,134
关键字:

jffs

友情链接: ImageUploaderPreChr.rar