⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scan.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			continue;		}		switch(je16_to_cpu(node->nodetype)) {		case JFFS2_NODETYPE_INODE:			if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) {				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);				D1(printk(KERN_DEBUG "Fewer than %zd bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n",					  sizeof(struct jffs2_raw_inode), buf_len, ofs));				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);				if (err)					return err;				buf_ofs = ofs;				node = (void *)buf;			}			err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs, s);			if (err) return err;			ofs += PAD(je32_to_cpu(node->totlen));			break;		case JFFS2_NODETYPE_DIRENT:			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);				D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n",					  je32_to_cpu(node->totlen), buf_len, ofs));				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);				if (err)					return err;				buf_ofs = ofs;				node = (void *)buf;			}			err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs, s);			if (err) return err;			ofs += PAD(je32_to_cpu(node->totlen));			break;#ifdef CONFIG_JFFS2_FS_XATTR		case JFFS2_NODETYPE_XATTR:			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);				D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"					  " left to end of buf. Reading 0x%x at 0x%08x\n",					  je32_to_cpu(node->totlen), buf_len, ofs));				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);				if (err)					return err;				buf_ofs = ofs;				node = (void *)buf;			}			err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);			if (err)				return err;			ofs += PAD(je32_to_cpu(node->totlen));			break;		case JFFS2_NODETYPE_XREF:			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);				D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"					  " left to end of buf. Reading 0x%x at 0x%08x\n",					  je32_to_cpu(node->totlen), buf_len, ofs));				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);				if (err)					return err;				buf_ofs = ofs;				node = (void *)buf;			}			err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);			if (err)				return err;			ofs += PAD(je32_to_cpu(node->totlen));			break;#endif	/* CONFIG_JFFS2_FS_XATTR */		case JFFS2_NODETYPE_CLEANMARKER:			D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));			if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",				       ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))					return err;				ofs += PAD(sizeof(struct jffs2_unknown_node));			} else if (jeb->first_node) {				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))					return err;				ofs += PAD(sizeof(struct jffs2_unknown_node));			} else {				jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);				ofs += PAD(c->cleanmarker_size);			}			break;		case JFFS2_NODETYPE_PADDING:			if (jffs2_sum_active())				jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))				return err;			ofs += PAD(je32_to_cpu(node->totlen));			break;		default:			switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {			case JFFS2_FEATURE_ROCOMPAT:				printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);				c->flags |= JFFS2_SB_FLAG_RO;				if (!(jffs2_is_readonly(c)))					return -EROFS;				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))					return err;				ofs += PAD(je32_to_cpu(node->totlen));				break;			case JFFS2_FEATURE_INCOMPAT:				printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);				return -EINVAL;			case JFFS2_FEATURE_RWCOMPAT_DELETE:				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))					return err;				ofs += PAD(je32_to_cpu(node->totlen));				break;			case JFFS2_FEATURE_RWCOMPAT_COPY: {				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));				jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);				/* We can't summarise nodes we don't grok */				jffs2_sum_disable_collecting(s);				ofs += PAD(je32_to_cpu(node->totlen));				break;				}			}		}	}	if (jffs2_sum_active()) {		if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) {			dbg_summary("There is not enough space for "				"summary information, disabling for this jeb!\n");			jffs2_sum_disable_collecting(s);		}	}	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",		  jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));		/* mark_node_obsolete can add to wasted !! */	if (jeb->wasted_size) {		jeb->dirty_size += jeb->wasted_size;		c->dirty_size += jeb->wasted_size;		c->wasted_size -= jeb->wasted_size;		jeb->wasted_size = 0;	}	return jffs2_scan_classify_jeb(c, jeb);}struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino){	struct jffs2_inode_cache *ic;	ic = jffs2_get_ino_cache(c, ino);	if (ic)		return ic;	if (ino > c->highest_ino)		c->highest_ino = ino;	ic = jffs2_alloc_inode_cache();	if (!ic) {		printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of inode cache failed\n");		return NULL;	}	memset(ic, 0, sizeof(*ic));	ic->ino = ino;	ic->nodes = (void *)ic;	jffs2_add_ino_cache(c, ic);	if (ino == 1)		ic->nlink = 1;	return ic;}static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s){	struct jffs2_inode_cache *ic;	uint32_t crc, ino = je32_to_cpu(ri->ino);	D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));	/* We do very little here now. Just check the ino# to which we should attribute	   this node; we can do all the CRC checking etc. later. There's a tradeoff here --	   we used to scan the flash once only, reading everything we want from it into	   memory, then building all our in-core data structures and freeing the extra	   information. Now we allow the first part of the mount to complete a lot quicker,	   but we have to go _back_ to the flash in order to finish the CRC checking, etc.	   Which means that the _full_ amount of time to get to proper write mode with GC	   operational may actually be _longer_ than before. Sucks to be me. */	/* Check the node CRC in any case. */	crc = crc32(0, ri, sizeof(*ri)-8);	if (crc != je32_to_cpu(ri->node_crc)) {		printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on "		       "node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",		       ofs, je32_to_cpu(ri->node_crc), crc);		/*		 * We believe totlen because the CRC on the node		 * _header_ was OK, just the node itself failed.		 */		return jffs2_scan_dirty_space(c, jeb,					      PAD(je32_to_cpu(ri->totlen)));	}	ic = jffs2_get_ino_cache(c, ino);	if (!ic) {		ic = jffs2_scan_make_ino_cache(c, ino);		if (!ic)			return -ENOMEM;	}	/* Wheee. It worked */	jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);	D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",		  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),		  je32_to_cpu(ri->offset),		  je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize)));	pseudo_random += je32_to_cpu(ri->version);	if (jffs2_sum_active()) {		jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);	}	return 0;}static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,				  struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s){	struct jffs2_full_dirent *fd;	struct jffs2_inode_cache *ic;	uint32_t checkedlen;	uint32_t crc;	int err;	D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));	/* We don't get here unless the node is still valid, so we don't have to	   mask in the ACCURATE bit any more. */	crc = crc32(0, rd, sizeof(*rd)-8);	if (crc != je32_to_cpu(rd->node_crc)) {		printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",		       ofs, je32_to_cpu(rd->node_crc), crc);		/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))			return err;		return 0;	}	pseudo_random += je32_to_cpu(rd->version);	/* Should never happen. Did. (OLPC trac #4184)*/	checkedlen = strnlen(rd->name, rd->nsize);	if (checkedlen < rd->nsize) {		printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars\n",		       ofs, checkedlen);	}	fd = jffs2_alloc_full_dirent(checkedlen+1);	if (!fd) {		return -ENOMEM;	}	memcpy(&fd->name, rd->name, checkedlen);	fd->name[checkedlen] = 0;	crc = crc32(0, fd->name, rd->nsize);	if (crc != je32_to_cpu(rd->name_crc)) {		printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",		       ofs, je32_to_cpu(rd->name_crc), crc);		D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino)));		jffs2_free_full_dirent(fd);		/* FIXME: Why do we believe totlen? */		/* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))			return err;		return 0;	}	ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));	if (!ic) {		jffs2_free_full_dirent(fd);		return -ENOMEM;	}	fd->raw = jffs2_link_node_ref(c, jeb, ofs | dirent_node_state(rd),				      PAD(je32_to_cpu(rd->totlen)), ic);	fd->next = NULL;	fd->version = je32_to_cpu(rd->version);	fd->ino = je32_to_cpu(rd->ino);	fd->nhash = full_name_hash(fd->name, checkedlen);	fd->type = rd->type;	jffs2_add_fd_to_list(c, fd, &ic->scan_dents);	if (jffs2_sum_active()) {		jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset);	}	return 0;}static int count_list(struct list_head *l){	uint32_t count = 0;	struct list_head *tmp;	list_for_each(tmp, l) {		count++;	}	return count;}/* Note: This breaks if list_empty(head). I don't care. You   might, if you copy this code and use it elsewhere :) */static void rotate_list(struct list_head *head, uint32_t count){	struct list_head *n = head->next;	list_del(head);	while(count--) {		n = n->next;	}	list_add(head, n);}void jffs2_rotate_lists(struct jffs2_sb_info *c){	uint32_t x;	uint32_t rotateby;	x = count_list(&c->clean_list);	if (x) {		rotateby = pseudo_random % x;		rotate_list((&c->clean_list), rotateby);	}	x = count_list(&c->very_dirty_list);	if (x) {		rotateby = pseudo_random % x;		rotate_list((&c->very_dirty_list), rotateby);	}	x = count_list(&c->dirty_list);	if (x) {		rotateby = pseudo_random % x;		rotate_list((&c->dirty_list), rotateby);	}	x = count_list(&c->erasable_list);	if (x) {		rotateby = pseudo_random % x;		rotate_list((&c->erasable_list), rotateby);	}	if (c->nr_erasing_blocks) {		rotateby = pseudo_random % c->nr_erasing_blocks;		rotate_list((&c->erase_pending_list), rotateby);	}	if (c->nr_free_blocks) {		rotateby = pseudo_random % c->nr_free_blocks;		rotate_list((&c->free_list), rotateby);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -