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

📄 nodelist.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		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);		}	}	jffs2_dbg_fragtree_paranoia_check_nolock(f);	return 0;}void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state){	spin_lock(&c->inocache_lock);	ic->state = state;	wake_up(&c->inocache_wq);	spin_unlock(&c->inocache_lock);}/* During mount, this needs no locking. During normal operation, its   callers want to do other stuff while still holding the inocache_lock.   Rather than introducing special case get_ino_cache functions or   callbacks, we just let the caller do the locking itself. */struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino){	struct jffs2_inode_cache *ret;	ret = c->inocache_list[ino % INOCACHE_HASHSIZE];	while (ret && ret->ino < ino) {		ret = ret->next;	}	if (ret && ret->ino != ino)		ret = NULL;	return ret;}void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new){	struct jffs2_inode_cache **prev;	spin_lock(&c->inocache_lock);	if (!new->ino)		new->ino = ++c->highest_ino;	dbg_inocache("add %p (ino #%u)\n", new, new->ino);	prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE];	while ((*prev) && (*prev)->ino < new->ino) {		prev = &(*prev)->next;	}	new->next = *prev;	*prev = new;	spin_unlock(&c->inocache_lock);}void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old){	struct jffs2_inode_cache **prev;#ifdef CONFIG_JFFS2_FS_XATTR	BUG_ON(old->xref);#endif	dbg_inocache("del %p (ino #%u)\n", old, old->ino);	spin_lock(&c->inocache_lock);	prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];	while ((*prev) && (*prev)->ino < old->ino) {		prev = &(*prev)->next;	}	if ((*prev) == old) {		*prev = old->next;	}	/* Free it now unless it's in READING or CLEARING state, which	   are the transitions upon read_inode() and clear_inode(). The	   rest of the time we know nobody else is looking at it, and	   if it's held by read_inode() or clear_inode() they'll free it	   for themselves. */	if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)		jffs2_free_inode_cache(old);	spin_unlock(&c->inocache_lock);}void jffs2_free_ino_caches(struct jffs2_sb_info *c){	int i;	struct jffs2_inode_cache *this, *next;	for (i=0; i<INOCACHE_HASHSIZE; i++) {		this = c->inocache_list[i];		while (this) {			next = this->next;			jffs2_xattr_free_inode(c, this);			jffs2_free_inode_cache(this);			this = next;		}		c->inocache_list[i] = NULL;	}}void jffs2_free_raw_node_refs(struct jffs2_sb_info *c){	int i;	struct jffs2_raw_node_ref *this, *next;	for (i=0; i<c->nr_blocks; i++) {		this = c->blocks[i].first_node;		while (this) {			if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)				next = this[REFS_PER_BLOCK].next_in_ino;			else				next = NULL;			jffs2_free_refblock(this);			this = next;		}		c->blocks[i].first_node = c->blocks[i].last_node = NULL;	}}struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset){	/* The common case in lookup is that there will be a node	   which precisely matches. So we go looking for that first */	struct rb_node *next;	struct jffs2_node_frag *prev = NULL;	struct jffs2_node_frag *frag = NULL;	dbg_fragtree2("root %p, offset %d\n", fragtree, offset);	next = fragtree->rb_node;	while(next) {		frag = rb_entry(next, struct jffs2_node_frag, rb);		if (frag->ofs + frag->size <= offset) {			/* Remember the closest smaller match on the way down */			if (!prev || frag->ofs > prev->ofs)				prev = frag;			next = frag->rb.rb_right;		} else if (frag->ofs > offset) {			next = frag->rb.rb_left;		} else {			return frag;		}	}	/* Exact match not found. Go back up looking at each parent,	   and return the closest smaller one */	if (prev)		dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n",			  prev->ofs, prev->ofs+prev->size);	else		dbg_fragtree2("returning NULL, empty fragtree\n");	return prev;}/* Pass 'c' argument to indicate that nodes should be marked obsolete as   they're killed. */void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c){	struct jffs2_node_frag *frag;	struct jffs2_node_frag *parent;	if (!root->rb_node)		return;	dbg_fragtree("killing\n");	frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb));	while(frag) {		if (frag->rb.rb_left) {			frag = frag_left(frag);			continue;		}		if (frag->rb.rb_right) {			frag = frag_right(frag);			continue;		}		if (frag->node && !(--frag->node->frags)) {			/* Not a hole, and it's the final remaining frag			   of this node. Free the node */			if (c)				jffs2_mark_node_obsolete(c, frag->node->raw);			jffs2_free_full_dnode(frag->node);		}		parent = frag_parent(frag);		if (parent) {			if (frag_left(parent) == frag)				parent->rb.rb_left = NULL;			else				parent->rb.rb_right = NULL;		}		jffs2_free_node_frag(frag);		frag = parent;		cond_resched();	}}struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,					       struct jffs2_eraseblock *jeb,					       uint32_t ofs, uint32_t len,					       struct jffs2_inode_cache *ic){	struct jffs2_raw_node_ref *ref;	BUG_ON(!jeb->allocated_refs);	jeb->allocated_refs--;	ref = jeb->last_node;	dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,		    ref->next_in_ino);	while (ref->flash_offset != REF_EMPTY_NODE) {		if (ref->flash_offset == REF_LINK_NODE)			ref = ref->next_in_ino;		else			ref++;	}	dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref, 		    ref->flash_offset, ofs, ref->next_in_ino, len);	ref->flash_offset = ofs;	if (!jeb->first_node) {		jeb->first_node = ref;		BUG_ON(ref_offset(ref) != jeb->offset);	} else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {		uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);		JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",			    ref, ref_offset(ref), ref_offset(ref)+len,			    ref_offset(jeb->last_node), 			    ref_offset(jeb->last_node)+last_len);		BUG();	}	jeb->last_node = ref;	if (ic) {		ref->next_in_ino = ic->nodes;		ic->nodes = ref;	} else {		ref->next_in_ino = NULL;	}	switch(ref_flags(ref)) {	case REF_UNCHECKED:		c->unchecked_size += len;		jeb->unchecked_size += len;		break;	case REF_NORMAL:	case REF_PRISTINE:		c->used_size += len;		jeb->used_size += len;		break;	case REF_OBSOLETE:		c->dirty_size += len;		jeb->dirty_size += len;		break;	}	c->free_size -= len;	jeb->free_size -= len;#ifdef TEST_TOTLEN	/* Set (and test) __totlen field... for now */	ref->__totlen = len;	ref_totlen(c, jeb, ref);#endif	return ref;}/* No locking, no reservation of 'ref'. Do not use on a live file system */int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,			   uint32_t size){	if (!size)		return 0;	if (unlikely(size > jeb->free_size)) {		printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",		       size, jeb->free_size, jeb->wasted_size);		BUG();	}	/* REF_EMPTY_NODE is !obsolete, so that works OK */	if (jeb->last_node && ref_obsolete(jeb->last_node)) {#ifdef TEST_TOTLEN		jeb->last_node->__totlen += size;#endif		c->dirty_size += size;		c->free_size -= size;		jeb->dirty_size += size;		jeb->free_size -= size;	} else {		uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;		ofs |= REF_OBSOLETE;		jffs2_link_node_ref(c, jeb, ofs, size, NULL);	}	return 0;}/* Calculate totlen from surrounding nodes or eraseblock */static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,				    struct jffs2_eraseblock *jeb,				    struct jffs2_raw_node_ref *ref){	uint32_t ref_end;	struct jffs2_raw_node_ref *next_ref = ref_next(ref);	if (next_ref)		ref_end = ref_offset(next_ref);	else {		if (!jeb)			jeb = &c->blocks[ref->flash_offset / c->sector_size];		/* Last node in block. Use free_space */		if (unlikely(ref != jeb->last_node)) {			printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",			       ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);			BUG();		}		ref_end = jeb->offset + c->sector_size - jeb->free_size;	}	return ref_end - ref_offset(ref);}uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,			    struct jffs2_raw_node_ref *ref){	uint32_t ret;	ret = __ref_totlen(c, jeb, ref);#ifdef TEST_TOTLEN	if (unlikely(ret != ref->__totlen)) {		if (!jeb)			jeb = &c->blocks[ref->flash_offset / c->sector_size];		printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",		       ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,		       ret, ref->__totlen);		if (ref_next(ref)) {			printk(KERN_CRIT "next %p (0x%08x-0x%08x)\n", ref_next(ref), ref_offset(ref_next(ref)),			       ref_offset(ref_next(ref))+ref->__totlen);		} else 			printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);		printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)		__jffs2_dbg_dump_node_refs_nolock(c, jeb);#endif		WARN_ON(1);		ret = ref->__totlen;	}#endif /* TEST_TOTLEN */	return ret;}

⌨️ 快捷键说明

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