JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target); 
dbg_readinode("symlink's target '%s' cached\n", f->target); 
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;	struct rb_root tn_list;	struct rb_node *rb, *repl_rb;	struct jffs2_full_dirent *fd_list;	struct jffs2_full_dnode *fn, *first_fn = NULL;	uint32_t crc;	uint32_t latest_mctime, mctime_ver;	size_t retlen;	int ret;	JFFS2_DBG_READINODE("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, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);	if (ret) {		JFFS2_ERROR("cannot read nodes for ino %u, returned error is %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;	rb = rb_first(&tn_list);	while (rb) {		cond_resched();		tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);		fn = tn->fn;		ret = 1;		JFFS2_DBG_READINODE("consider node ver %u, phys offset "			"%#08x(%d), range %u-%u.\n", tn->version,			ref_offset(fn->raw), ref_flags(fn->raw),			fn->ofs, fn->ofs + fn->size);		if (fn->size) {			ret = jffs2_add_older_frag_to_fragtree(c, f, tn);			/* TODO: the error code isn't checked, check it */			jffs2_dbg_fragtree_paranoia_check_nolock(f);			BUG_ON(ret < 0);			if (!first_fn && ret == 0)				first_fn = fn;		} else if (!first_fn) {			first_fn = fn;			f->metadata = fn;			ret = 0; /* Prevent freeing the metadata update node */		} else			jffs2_mark_node_obsolete(c, fn->raw);					BUG_ON(rb->rb_left);		if (rb->rb_parent && rb->rb_parent->rb_left == rb) {			/* We were then left-hand child of our parent. We need			 * to move our own right-hand child into our place. */			repl_rb = rb->rb_right;			if (repl_rb)				repl_rb->rb_parent = rb->rb_parent;		} else			repl_rb = NULL;		rb = rb_next(rb);		/* Remove the spent tn from the tree; don't bother rebalancing		 * but put our right-hand child in our own place. */		if (tn->rb.rb_parent) {			if (tn->rb.rb_parent->rb_left == &tn->rb)				tn->rb.rb_parent->rb_left = repl_rb;			else if (tn->rb.rb_parent->rb_right == &tn->rb)				tn->rb.rb_parent->rb_right = repl_rb;			else BUG();		} else if (tn->rb.rb_right)			tn->rb.rb_right->rb_parent = NULL;		jffs2_free_tmp_dnode_info(tn);		if (ret) {			JFFS2_DBG_READINODE("delete dnode %u-%u.\n",				fn->ofs, fn->ofs + fn->size);			jffs2_free_full_dnode(fn);		}	}	jffs2_dbg_fragtree_paranoia_check_nolock(f);	BUG_ON(first_fn && ref_obsolete(first_fn->raw));	fn = first_fn;	if (unlikely(!first_fn)) {		/* No data nodes for this inode. */		if (f->inocache->ino != 1) {			JFFS2_WARNING("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;			}			JFFS2_NOTICE("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)) {		JFFS2_ERROR("failed to read from flash: error %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)) {		JFFS2_ERROR("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_fragtree(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;		if (f->inocache->state != INO_STATE_CHECKING) {			/* Symlink's inode data is the target path. Read it and			 * keep in RAM to facilitate quick follow symlink			 * operation. */			f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);			if (!f->target) {				JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));				up(&f->sem);				jffs2_do_clear_inode(c, f);				return -ENOMEM;			}						ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),						je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);						if (ret  || retlen != je32_to_cpu(latest_node->csize)) {				if (retlen != je32_to_cpu(latest_node->csize))					ret = -EIO;				kfree(f->target);				f->target = NULL;				up(&f->sem);				jffs2_do_clear_inode(c, f);				return -ret;			}			f->target[je32_to_cpu(latest_node->csize)] = '\0';			JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target);		}				/* 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) {			JFFS2_ERROR("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)) {			JFFS2_ERROR("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))) {			JFFS2_ERROR("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;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/733802d974e5af42acb7cd61b16c0ce6dd03b7ed/readinode.c/clean/fs/jffs2/readinode.c