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

📄 readinode.c

📁 jffs2源代码基于2。6内核
💻 C
📖 第 1 页 / 共 2 页
字号:
			return 0;		}	}	/* OK, now we have newfrag added in the correct place in the tree, but	   frag_next(newfrag) may be a fragment which is overlapped by it 	*/	while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) {		/* 'this' frag is obsoleted completely. */		D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size));		rb_erase(&this->rb, list);		jffs2_obsolete_node_frag(c, this);	}	/* Now we're pointing at the first frag which isn't totally obsoleted by 	   the new frag */	if (!this || newfrag->ofs + newfrag->size == this->ofs) {		return 0;	}	/* Still some overlap but we don't need to move it in the tree */	this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);	this->ofs = newfrag->ofs + newfrag->size;	/* And mark them REF_NORMAL so the GC takes a look at them */	if (this->node)		mark_ref_normal(this->node->raw);	mark_ref_normal(newfrag->node->raw);	return 0;}void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size){	struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);	D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size));	/* We know frag->ofs <= size. That's what lookup does for us */	if (frag && frag->ofs != size) {		if (frag->ofs+frag->size >= size) {			D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));			frag->size = size - frag->ofs;		}		frag = frag_next(frag);	}	while (frag && frag->ofs >= size) {		struct jffs2_node_frag *next = frag_next(frag);		D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));		frag_erase(frag, list);		jffs2_obsolete_node_frag(c, frag);		frag = next;	}}/* Scan the list of all nodes present for this ino, build map of versions, etc. */static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, 					struct jffs2_inode_info *f,					struct jffs2_raw_inode *latest_node);int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 			uint32_t ino, struct jffs2_raw_inode *latest_node){	D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); retry_inocache:	spin_lock(&c->inocache_lock);	f->inocache = jffs2_get_ino_cache(c, ino);	D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache));	if (f->inocache) {		/* Check its state. We may need to wait before we can use it */		switch(f->inocache->state) {		case INO_STATE_UNCHECKED:		case INO_STATE_CHECKEDABSENT:			f->inocache->state = INO_STATE_READING;			break;					case INO_STATE_CHECKING:		case INO_STATE_GC:			/* If it's in either of these states, we need			   to wait for whoever's got it to finish and			   put it back. */			D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n",				  ino, f->inocache->state));			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);			goto retry_inocache;		case INO_STATE_READING:		case INO_STATE_PRESENT:			/* Eep. This should never happen. It can			happen if Linux calls read_inode() again			before clear_inode() has finished though. */			printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);			/* Fail. That's probably better than allowing it to succeed */			f->inocache = NULL;			break;		default:			BUG();		}	}	spin_unlock(&c->inocache_lock);	if (!f->inocache && ino == 1) {		/* Special case - no root inode on medium */		f->inocache = jffs2_alloc_inode_cache();		if (!f->inocache) {			printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n");			return -ENOMEM;		}		D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n"));		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));		f->inocache->ino = f->inocache->nlink = 1;		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;		f->inocache->state = INO_STATE_READING;		jffs2_add_ino_cache(c, f->inocache);	}	if (!f->inocache) {		printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino);		return -ENOENT;	}	return jffs2_do_read_inode_internal(c, f, latest_node);}int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic){	struct jffs2_raw_inode n;	struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);	int ret;	if (!f)		return -ENOMEM;	memset(f, 0, sizeof(*f));	init_MUTEX_LOCKED(&f->sem);	f->inocache = ic;	ret = jffs2_do_read_inode_internal(c, f, &n);	if (!ret) {		up(&f->sem);		jffs2_do_clear_inode(c, f);	}	kfree (f);	return ret;}static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, 					struct jffs2_inode_info *f,					struct jffs2_raw_inode *latest_node){	struct jffs2_tmp_dnode_info *tn_list, *tn;	struct jffs2_full_dirent *fd_list;	struct jffs2_full_dnode *fn = NULL;	uint32_t crc;	uint32_t latest_mctime, mctime_ver;	uint32_t mdata_ver = 0;	size_t retlen;	int ret;	D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink));	/* Grab all nodes relevant to this ino */	ret = jffs2_get_inode_nodes(c, f->inocache->ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);	if (ret) {		printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret);		if (f->inocache->state == INO_STATE_READING)			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);		return ret;	}	f->dents = fd_list;	while (tn_list) {		tn = tn_list;		fn = tn->fn;		if (f->metadata) {			if (likely(tn->version >= mdata_ver)) {				D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)));				jffs2_mark_node_obsolete(c, f->metadata->raw);				jffs2_free_full_dnode(f->metadata);				f->metadata = NULL;								mdata_ver = 0;			} else {				/* This should never happen. */				printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n",					  ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw));				jffs2_mark_node_obsolete(c, fn->raw);				jffs2_free_full_dnode(fn);				/* Fill in latest_node from the metadata, not this one we're about to free... */				fn = f->metadata;				goto next_tn;			}		}		if (fn->size) {			jffs2_add_full_dnode_to_inode(c, f, fn);		} else {			/* Zero-sized node at end of version list. Just a metadata update */			D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version));			f->metadata = fn;			mdata_ver = tn->version;		}	next_tn:		tn_list = tn->next;		jffs2_free_tmp_dnode_info(tn);	}	D1(jffs2_sanitycheck_fragtree(f));	if (!fn) {		/* No data nodes for this inode. */		if (f->inocache->ino != 1) {			printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino);			if (!fd_list) {				if (f->inocache->state == INO_STATE_READING)					jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);				return -EIO;			}			printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n");		}		latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);		latest_node->version = cpu_to_je32(0);		latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);		latest_node->isize = cpu_to_je32(0);		latest_node->gid = cpu_to_je16(0);		latest_node->uid = cpu_to_je16(0);		if (f->inocache->state == INO_STATE_READING)			jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);		return 0;	}	ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);	if (ret || retlen != sizeof(*latest_node)) {		printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n",		       ret, retlen, sizeof(*latest_node));		/* FIXME: If this fails, there seems to be a memory leak. Find it. */		up(&f->sem);		jffs2_do_clear_inode(c, f);		return ret?ret:-EIO;	}	crc = crc32(0, latest_node, sizeof(*latest_node)-8);	if (crc != je32_to_cpu(latest_node->node_crc)) {		printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw));		up(&f->sem);		jffs2_do_clear_inode(c, f);		return -EIO;	}	switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {	case S_IFDIR:		if (mctime_ver > je32_to_cpu(latest_node->version)) {			/* The times in the latest_node are actually older than			   mctime in the latest dirent. Cheat. */			latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);		}		break;				case S_IFREG:		/* If it was a regular file, truncate it to the latest node's isize */		jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize));		break;	case S_IFLNK:		/* Hack to work around broken isize in old symlink code.		   Remove this when dwmw2 comes to his senses and stops		   symlinks from being an entirely gratuitous special		   case. */		if (!je32_to_cpu(latest_node->isize))			latest_node->isize = latest_node->dsize;		/* fall through... */	case S_IFBLK:	case S_IFCHR:		/* Certain inode types should have only one data node, and it's		   kept as the metadata node */		if (f->metadata) {			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n",			       f->inocache->ino, jemode_to_cpu(latest_node->mode));			up(&f->sem);			jffs2_do_clear_inode(c, f);			return -EIO;		}		if (!frag_first(&f->fragtree)) {			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n",			       f->inocache->ino, jemode_to_cpu(latest_node->mode));			up(&f->sem);			jffs2_do_clear_inode(c, f);			return -EIO;		}		/* ASSERT: f->fraglist != NULL */		if (frag_next(frag_first(&f->fragtree))) {			printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n",			       f->inocache->ino, jemode_to_cpu(latest_node->mode));			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */			up(&f->sem);			jffs2_do_clear_inode(c, f);			return -EIO;		}		/* OK. We're happy */		f->metadata = frag_first(&f->fragtree)->node;		jffs2_free_node_frag(frag_first(&f->fragtree));		f->fragtree = RB_ROOT;		break;	}	if (f->inocache->state == INO_STATE_READING)		jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);	return 0;}void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f){	struct jffs2_full_dirent *fd, *fds;	int deleted;	down(&f->sem);	deleted = f->inocache && !f->inocache->nlink;	if (f->metadata) {		if (deleted)			jffs2_mark_node_obsolete(c, f->metadata->raw);		jffs2_free_full_dnode(f->metadata);	}	jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);	fds = f->dents;	while(fds) {		fd = fds;		fds = fd->next;		jffs2_free_full_dirent(fd);	}	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);	up(&f->sem);}

⌨️ 快捷键说明

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