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

📄 scan.c

📁 jffs2源代码基于2。6内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {			printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);			printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");			DIRTY_SPACE(4);			ofs += 4;			continue;		}		if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) {			/* OK. We're out of possibilities. Whinge and move on */			noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", 				     JFFS2_MAGIC_BITMASK, ofs, 				     je16_to_cpu(node->magic));			DIRTY_SPACE(4);			ofs += 4;			continue;		}		/* We seem to have a node of sorts. Check the CRC */		crcnode.magic = node->magic;		crcnode.nodetype = cpu_to_je16( je16_to_cpu(node->nodetype) | JFFS2_NODE_ACCURATE);		crcnode.totlen = node->totlen;		hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4);		if (hdr_crc != je32_to_cpu(node->hdr_crc)) {			noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n",				     ofs, je16_to_cpu(node->magic),				     je16_to_cpu(node->nodetype), 				     je32_to_cpu(node->totlen),				     je32_to_cpu(node->hdr_crc),				     hdr_crc);			DIRTY_SPACE(4);			ofs += 4;			continue;		}		if (ofs + je32_to_cpu(node->totlen) > 		    jeb->offset + c->sector_size) {			/* Eep. Node goes over the end of the erase block. */			printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",			       ofs, je32_to_cpu(node->totlen));			printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");			DIRTY_SPACE(4);			ofs += 4;			continue;		}		if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {			/* Wheee. This is an obsoleted node */			D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));			DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));			ofs += PAD(je32_to_cpu(node->totlen));			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);			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);			if (err) return err;			ofs += PAD(je32_to_cpu(node->totlen));			break;		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);				DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));				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);				DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));				ofs += PAD(sizeof(struct jffs2_unknown_node));			} else {				struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();				if (!marker_ref) {					printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");					return -ENOMEM;				}				marker_ref->next_in_ino = NULL;				marker_ref->next_phys = NULL;				marker_ref->flash_offset = ofs | REF_NORMAL;				marker_ref->__totlen = c->cleanmarker_size;				jeb->first_node = jeb->last_node = marker_ref;			     				USED_SPACE(PAD(c->cleanmarker_size));				ofs += PAD(c->cleanmarker_size);			}			break;		case JFFS2_NODETYPE_PADDING:			DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));			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;				DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));				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));				DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));				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));				USED_SPACE(PAD(je32_to_cpu(node->totlen)));				ofs += PAD(je32_to_cpu(node->totlen));				break;			}		}	}	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, 		  jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_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;	}	if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size 		&& (!jeb->first_node || !jeb->first_node->next_in_ino) )		return BLK_STATE_CLEANMARKER;			/* move blocks with max 4 byte dirty space to cleanlist */		else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) {		c->dirty_size -= jeb->dirty_size;		c->wasted_size += jeb->dirty_size; 		jeb->wasted_size += jeb->dirty_size;		jeb->dirty_size = 0;		return BLK_STATE_CLEAN;	} else if (jeb->used_size || jeb->unchecked_size)		return BLK_STATE_PARTDIRTY;	else		return BLK_STATE_ALLDIRTY;}static 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_raw_node_ref *raw;	struct jffs2_inode_cache *ic;	uint32_t 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. */	raw = jffs2_alloc_raw_node_ref();	if (!raw) {		printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");		return -ENOMEM;	}	ic = jffs2_get_ino_cache(c, ino);	if (!ic) {		/* Inocache get failed. Either we read a bogus ino# or it's just genuinely the		   first node we found for this inode. Do a CRC check to protect against the former		   case */		uint32_t 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. */			DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));			jffs2_free_raw_node_ref(raw);			return 0;		}		ic = jffs2_scan_make_ino_cache(c, ino);		if (!ic) {			jffs2_free_raw_node_ref(raw);			return -ENOMEM;		}	}	/* Wheee. It worked */	raw->flash_offset = ofs | REF_UNCHECKED;	raw->__totlen = PAD(je32_to_cpu(ri->totlen));	raw->next_phys = NULL;	raw->next_in_ino = ic->nodes;	ic->nodes = raw;	if (!jeb->first_node)		jeb->first_node = raw;	if (jeb->last_node)		jeb->last_node->next_phys = raw;	jeb->last_node = raw;	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);	UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));	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_raw_node_ref *raw;	struct jffs2_full_dirent *fd;	struct jffs2_inode_cache *ic;	uint32_t crc;	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. */		DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));		return 0;	}	pseudo_random += je32_to_cpu(rd->version);	fd = jffs2_alloc_full_dirent(rd->nsize+1);	if (!fd) {		return -ENOMEM;	}	memcpy(&fd->name, rd->name, rd->nsize);	fd->name[rd->nsize] = 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. */		DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));		return 0;	}	raw = jffs2_alloc_raw_node_ref();	if (!raw) {		jffs2_free_full_dirent(fd);		printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");		return -ENOMEM;	}	ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));	if (!ic) {		jffs2_free_full_dirent(fd);		jffs2_free_raw_node_ref(raw);		return -ENOMEM;	}		raw->__totlen = PAD(je32_to_cpu(rd->totlen));	raw->flash_offset = ofs | REF_PRISTINE;	raw->next_phys = NULL;	raw->next_in_ino = ic->nodes;	ic->nodes = raw;	if (!jeb->first_node)		jeb->first_node = raw;	if (jeb->last_node)		jeb->last_node->next_phys = raw;	jeb->last_node = raw;	fd->raw = raw;	fd->next = NULL;	fd->version = je32_to_cpu(rd->version);	fd->ino = je32_to_cpu(rd->ino);	fd->nhash = full_name_hash(fd->name, rd->nsize);	fd->type = rd->type;	USED_SPACE(PAD(je32_to_cpu(rd->totlen)));	jffs2_add_fd_to_list(c, fd, &ic->scan_dents);	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;		D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby));		rotate_list((&c->clean_list), rotateby);		D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n",			  list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset));	} else {		D1(printk(KERN_DEBUG "Not rotating empty clean_list\n"));	}	x = count_list(&c->very_dirty_list);	if (x) {		rotateby = pseudo_random % x;		D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby));		rotate_list((&c->very_dirty_list), rotateby);		D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n",			  list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset));	} else {		D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n"));	}	x = count_list(&c->dirty_list);	if (x) {		rotateby = pseudo_random % x;		D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby));		rotate_list((&c->dirty_list), rotateby);		D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n",			  list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset));	} else {		D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n"));	}	x = count_list(&c->erasable_list);	if (x) {		rotateby = pseudo_random % x;		D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby));		rotate_list((&c->erasable_list), rotateby);		D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n",			  list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset));	} else {		D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n"));	}	if (c->nr_erasing_blocks) {		rotateby = pseudo_random % c->nr_erasing_blocks;		D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby));		rotate_list((&c->erase_pending_list), rotateby);		D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n",			  list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset));	} else {		D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n"));	}	if (c->nr_free_blocks) {		rotateby = pseudo_random % c->nr_free_blocks;		D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby));		rotate_list((&c->free_list), rotateby);		D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n",			  list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset));	} else {		D1(printk(KERN_DEBUG "Not rotating empty free_list\n"));	}}

⌨️ 快捷键说明

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