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

📄 readinode.c

📁 jffs2源代码基于2。6内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * JFFS2 -- Journalling Flash File System, Version 2. * * Copyright (C) 2001-2003 Red Hat, Inc. * * Created by David Woodhouse <dwmw2@redhat.com> * * For licensing information, see the file 'LICENCE' in this directory. * * $Id: readinode.c,v 1.113 2003/11/03 13:20:33 dwmw2 Exp $ * */#include <linux/kernel.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/crc32.h>#include <linux/pagemap.h>#include <linux/mtd/mtd.h>#include <linux/compiler.h>#include "nodelist.h"static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag);#if CONFIG_JFFS2_FS_DEBUG >= 1static void jffs2_print_fragtree(struct rb_root *list, int permitbug){	struct jffs2_node_frag *this = frag_first(list);	uint32_t lastofs = 0;	int buggy = 0;	while(this) {		if (this->node)			printk(KERN_DEBUG "frag %04x-%04x: 0x%08x(%d) on flash (*%p). left (%p), right (%p), parent (%p)\n",			       this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw),			       this, frag_left(this), frag_right(this), frag_parent(this));		else 			printk(KERN_DEBUG "frag %04x-%04x: hole (*%p). left (%p} right (%p), parent (%p)\n", this->ofs, 			       this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this));		if (this->ofs != lastofs)			buggy = 1;		lastofs = this->ofs+this->size;		this = frag_next(this);	}	if (buggy && !permitbug) {		printk(KERN_CRIT "Frag tree got a hole in it\n");		BUG();	}}void jffs2_print_frag_list(struct jffs2_inode_info *f){	jffs2_print_fragtree(&f->fragtree, 0);	if (f->metadata) {		printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));	}}static int jffs2_sanitycheck_fragtree(struct jffs2_inode_info *f){	struct jffs2_node_frag *frag;	int bitched = 0;	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {		struct jffs2_full_dnode *fn = frag->node;		if (!fn || !fn->raw)			continue;		if (ref_flags(fn->raw) == REF_PRISTINE) {			if (fn->frags > 1) {				printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(fn->raw), fn->frags);				bitched = 1;			}			/* A hole node which isn't multi-page should be garbage-collected			   and merged anyway, so we just check for the frag size here,			   rather than mucking around with actually reading the node			   and checking the compression type, which is the real way			   to tell a hole node. */			if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {				printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n",				       ref_offset(fn->raw));				bitched = 1;			}			if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {				printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n",				       ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);				bitched = 1;			}		}	}		if (bitched) {		struct jffs2_node_frag *thisfrag;		printk(KERN_WARNING "Inode is #%u\n", f->inocache->ino);		thisfrag = frag_first(&f->fragtree);		while (thisfrag) {			if (!thisfrag->node) {				printk("Frag @0x%x-0x%x; node-less hole\n",				       thisfrag->ofs, thisfrag->size + thisfrag->ofs);			} else if (!thisfrag->node->raw) {				printk("Frag @0x%x-0x%x; raw-less hole\n",				       thisfrag->ofs, thisfrag->size + thisfrag->ofs);			} else {				printk("Frag @0x%x-0x%x; raw at 0x%08x(%d) (0x%x-0x%x)\n",				       thisfrag->ofs, thisfrag->size + thisfrag->ofs,				       ref_offset(thisfrag->node->raw), ref_flags(thisfrag->node->raw),				       thisfrag->node->ofs, thisfrag->node->ofs+thisfrag->node->size);			}			thisfrag = frag_next(thisfrag);		}	}	return bitched;}#endif /* D1 */static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this){	if (this->node) {		this->node->frags--;		if (!this->node->frags) {			/* The node has no valid frags left. It's totally obsoleted */			D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",				  ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size));			jffs2_mark_node_obsolete(c, this->node->raw);			jffs2_free_full_dnode(this->node);		} else {			D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n",				  ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size,				  this->node->frags));			mark_ref_normal(this->node->raw);		}			}	jffs2_free_node_frag(this);}/* Given an inode, probably with existing list of fragments, add the new node * to the fragment list. */int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn){	int ret;	struct jffs2_node_frag *newfrag;	D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn));	newfrag = jffs2_alloc_node_frag();	if (unlikely(!newfrag))		return -ENOMEM;	D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n",		  fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag));		if (unlikely(!fn->size)) {		jffs2_free_node_frag(newfrag);		return 0;	}	newfrag->ofs = fn->ofs;	newfrag->size = fn->size;	newfrag->node = fn;	newfrag->node->frags = 1;	ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag);	if (ret)		return ret;	/* If we now share a page with other nodes, mark either previous	   or next node REF_NORMAL, as appropriate.  */	if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) {		struct jffs2_node_frag *prev = frag_prev(newfrag);		mark_ref_normal(fn->raw);		/* If we don't start at zero there's _always_ a previous */			if (prev->node)			mark_ref_normal(prev->node->raw);	}	if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) {		struct jffs2_node_frag *next = frag_next(newfrag);				if (next) {			mark_ref_normal(fn->raw);			if (next->node)				mark_ref_normal(next->node->raw);		}	}	D2(if (jffs2_sanitycheck_fragtree(f)) {		   printk(KERN_WARNING "Just added node %04x-%04x @0x%08x on flash, newfrag *%p\n",			  fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag);		   return 0;	   })	D2(jffs2_print_frag_list(f));	return 0;}/* Doesn't set inode->i_size */static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag){	struct jffs2_node_frag *this;	uint32_t lastend;	/* Skip all the nodes which are completed before this one starts */	this = jffs2_lookup_node_frag(list, newfrag->node->ofs);	if (this) {		D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",			  this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this));		lastend = this->ofs + this->size;	} else {		D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n"));		lastend = 0;	}			  	/* See if we ran off the end of the list */	if (lastend <= newfrag->ofs) {		/* We did */		/* Check if 'this' node was on the same page as the new node.		   If so, both 'this' and the new node get marked REF_NORMAL so		   the GC can take a look.		*/		if ((lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) {			if (this->node)				mark_ref_normal(this->node->raw);			mark_ref_normal(newfrag->node->raw);		}		if (lastend < newfrag->node->ofs) {			/* ... and we need to put a hole in before the new node */			struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();			if (!holefrag) {				jffs2_free_node_frag(newfrag);				return -ENOMEM;			}			holefrag->ofs = lastend;			holefrag->size = newfrag->node->ofs - lastend;			holefrag->node = NULL;			if (this) {				/* By definition, the 'this' node has no right-hand child, 				   because there are no frags with offset greater than it.				   So that's where we want to put the hole */				D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this));				rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right);			} else {				D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag));				rb_link_node(&holefrag->rb, NULL, &list->rb_node);			}			rb_insert_color(&holefrag->rb, list);			this = holefrag;		}		if (this) {			/* By definition, the 'this' node has no right-hand child, 			   because there are no frags with offset greater than it.			   So that's where we want to put the hole */			D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this));			rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);					} else {			D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag));			rb_link_node(&newfrag->rb, NULL, &list->rb_node);		}		rb_insert_color(&newfrag->rb, list);		return 0;	}	D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", 		  this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this));	/* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes,	 * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs  	 */	if (newfrag->ofs > this->ofs) {		/* This node isn't completely obsoleted. The start of it remains valid */		/* Mark the new node and the partially covered node REF_NORMAL -- let		   the GC take a look at them */		mark_ref_normal(newfrag->node->raw);		if (this->node)			mark_ref_normal(this->node->raw);		if (this->ofs + this->size > newfrag->ofs + newfrag->size) {			/* The new node splits 'this' frag into two */			struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag();			if (!newfrag2) {				jffs2_free_node_frag(newfrag);				return -ENOMEM;			}			D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size);			if (this->node)				printk("phys 0x%08x\n", ref_offset(this->node->raw));			else 				printk("hole\n");			   )						/* New second frag pointing to this's node */			newfrag2->ofs = newfrag->ofs + newfrag->size;			newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;			newfrag2->node = this->node;			if (this->node)				this->node->frags++;			/* Adjust size of original 'this' */			this->size = newfrag->ofs - this->ofs;			/* Now, we know there's no node with offset			   greater than this->ofs but smaller than			   newfrag2->ofs or newfrag->ofs, for obvious			   reasons. So we can do a tree insert from			   'this' to insert newfrag, and a tree insert			   from newfrag to insert newfrag2. */			jffs2_fragtree_insert(newfrag, this);			rb_insert_color(&newfrag->rb, list);						jffs2_fragtree_insert(newfrag2, newfrag);			rb_insert_color(&newfrag2->rb, list);						return 0;		}		/* New node just reduces 'this' frag in size, doesn't split it */		this->size = newfrag->ofs - this->ofs;		/* Again, we know it lives down here in the tree */		jffs2_fragtree_insert(newfrag, this);		rb_insert_color(&newfrag->rb, list);	} else {		/* New frag starts at the same point as 'this' used to. Replace 		   it in the tree without doing a delete and insertion */		D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n",			  newfrag, newfrag->ofs, newfrag->ofs+newfrag->size,			  this, this->ofs, this->ofs+this->size));			rb_replace_node(&this->rb, &newfrag->rb, list);				if (newfrag->ofs + newfrag->size >= this->ofs+this->size) {			D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size));			jffs2_obsolete_node_frag(c, this);		} else {			this->ofs += newfrag->size;			this->size -= newfrag->size;			jffs2_fragtree_insert(this, newfrag);			rb_insert_color(&this->rb, list);

⌨️ 快捷键说明

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