/* FIXME: If we're deleting a dirent which contains the current mtime and ctime, we should update the metadata node with those times accordingly */  
static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 					struct jffs2_inode_info *f, struct jffs2_full_dirent *fd){	struct jffs2_full_dirent **fdp = &f->dents;	int found = 0;	/* On a medium where we can't actually mark nodes obsolete	   pernamently, such as NAND flash, we need to work out	   whether this deletion dirent is still needed to actively	   delete a 'real' dirent with the same name that's still	   somewhere else on the flash. */	if (!jffs2_can_mark_obsolete(c)) {		struct jffs2_raw_dirent *rd;		struct jffs2_raw_node_ref *raw;		int ret;		size_t retlen;		int name_len = strlen(fd->name);		uint32_t name_crc = crc32(0, fd->name, name_len);		uint32_t rawlen = ref_totlen(c, jeb, fd->raw);		rd = kmalloc(rawlen, GFP_KERNEL);		if (!rd)			return -ENOMEM;		/* Prevent the erase code from nicking the obsolete node refs while		   we're looking at them. I really don't like this extra lock but		   can't see any alternative. Suggestions on a postcard to... */		down(&c->erase_free_sem);		for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {			/* We only care about obsolete ones */			if (!(ref_obsolete(raw)))				continue;			/* Any dirent with the same name is going to have the same length... */			if (ref_totlen(c, NULL, raw) != rawlen)				continue;			/* Doesn't matter if there's one in the same erase block. We're going to 			   delete it too at the same time. */			if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset))				continue;			D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw)));			/* This is an obsolete node belonging to the same directory, and it's of the right			   length. We need to take a closer look...*/			ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd);			if (ret) {				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading obsolete node at %08x\n", ret, ref_offset(raw));				/* If we can't read it, we don't need to continue to obsolete it. Continue */				continue;			}			if (retlen != rawlen) {				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %u) reading header from obsolete node at %08x\n",				       retlen, rawlen, ref_offset(raw));				continue;			}			if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT)				continue;			/* If the name CRC doesn't match, skip */			if (je32_to_cpu(rd->name_crc) != name_crc)				continue;			/* If the name length doesn't match, or it's another deletion dirent, skip */			if (rd->nsize != name_len || !je32_to_cpu(rd->ino))				continue;			/* OK, check the actual name now */			if (memcmp(rd->name, fd->name, name_len))				continue;			/* OK. The name really does match. There really is still an older node on			   the flash which our deletion dirent obsoletes. So we have to write out			   a new deletion dirent to replace it */			up(&c->erase_free_sem);			D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",				  ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));			kfree(rd);			return jffs2_garbage_collect_dirent(c, jeb, f, fd);		}		up(&c->erase_free_sem);		kfree(rd);	}	/* No need for it any more. Just mark it obsolete and remove it from the list */	while (*fdp) {		if ((*fdp) == fd) {			found = 1;			*fdp = fd->next;			break;		}		fdp = &(*fdp)->next;	}	if (!found) {		printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%u\n", fd->name, f->inocache->ino);	}	jffs2_mark_node_obsolete(c, fd->raw);	jffs2_free_full_dirent(fd);	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/3a69e0cd22cf34920508a4032d53e41251925f53/gc.c/clean/fs/jffs2/gc.c