xref: /openbmc/linux/fs/jffs2/gc.c (revision e9b5b23e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * JFFS2 -- Journalling Flash File System, Version 2.
31da177e4SLinus Torvalds  *
4c00c310eSDavid Woodhouse  * Copyright © 2001-2007 Red Hat, Inc.
56088c058SDavid Woodhouse  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Created by David Woodhouse <dwmw2@infradead.org>
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * For licensing information, see the file 'LICENCE' in this directory.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
135a528957SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
145a528957SJoe Perches 
151da177e4SLinus Torvalds #include <linux/kernel.h>
161da177e4SLinus Torvalds #include <linux/mtd/mtd.h>
171da177e4SLinus Torvalds #include <linux/slab.h>
181da177e4SLinus Torvalds #include <linux/pagemap.h>
191da177e4SLinus Torvalds #include <linux/crc32.h>
201da177e4SLinus Torvalds #include <linux/compiler.h>
211da177e4SLinus Torvalds #include <linux/stat.h>
221da177e4SLinus Torvalds #include "nodelist.h"
231da177e4SLinus Torvalds #include "compr.h"
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
261da177e4SLinus Torvalds 					  struct jffs2_inode_cache *ic,
271da177e4SLinus Torvalds 					  struct jffs2_raw_node_ref *raw);
281da177e4SLinus Torvalds static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
291da177e4SLinus Torvalds 					struct jffs2_inode_info *f, struct jffs2_full_dnode *fd);
301da177e4SLinus Torvalds static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
311da177e4SLinus Torvalds 					struct jffs2_inode_info *f, struct jffs2_full_dirent *fd);
321da177e4SLinus Torvalds static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
331da177e4SLinus Torvalds 					struct jffs2_inode_info *f, struct jffs2_full_dirent *fd);
341da177e4SLinus Torvalds static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
351da177e4SLinus Torvalds 				      struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
361da177e4SLinus Torvalds 				      uint32_t start, uint32_t end);
371da177e4SLinus Torvalds static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
381da177e4SLinus Torvalds 				       struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
391da177e4SLinus Torvalds 				       uint32_t start, uint32_t end);
401da177e4SLinus Torvalds static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_eraseblock *jeb,
411da177e4SLinus Torvalds 			       struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f);
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds /* Called with erase_completion_lock held */
jffs2_find_gc_block(struct jffs2_sb_info * c)441da177e4SLinus Torvalds static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds 	struct jffs2_eraseblock *ret;
471da177e4SLinus Torvalds 	struct list_head *nextlist = NULL;
481da177e4SLinus Torvalds 	int n = jiffies % 128;
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds 	/* Pick an eraseblock to garbage collect next. This is where we'll
511da177e4SLinus Torvalds 	   put the clever wear-levelling algorithms. Eventually.  */
521da177e4SLinus Torvalds 	/* We possibly want to favour the dirtier blocks more when the
531da177e4SLinus Torvalds 	   number of free blocks is low. */
54a42163d7SArtem B. Bityuckiy again:
551da177e4SLinus Torvalds 	if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > c->resv_blocks_gcbad) {
569c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from bad_used_list to GC next\n");
571da177e4SLinus Torvalds 		nextlist = &c->bad_used_list;
581da177e4SLinus Torvalds 	} else if (n < 50 && !list_empty(&c->erasable_list)) {
591da177e4SLinus Torvalds 		/* Note that most of them will have gone directly to be erased.
601da177e4SLinus Torvalds 		   So don't favour the erasable_list _too_ much. */
619c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from erasable_list to GC next\n");
621da177e4SLinus Torvalds 		nextlist = &c->erasable_list;
631da177e4SLinus Torvalds 	} else if (n < 110 && !list_empty(&c->very_dirty_list)) {
641da177e4SLinus Torvalds 		/* Most of the time, pick one off the very_dirty list */
659c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from very_dirty_list to GC next\n");
661da177e4SLinus Torvalds 		nextlist = &c->very_dirty_list;
671da177e4SLinus Torvalds 	} else if (n < 126 && !list_empty(&c->dirty_list)) {
689c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from dirty_list to GC next\n");
691da177e4SLinus Torvalds 		nextlist = &c->dirty_list;
701da177e4SLinus Torvalds 	} else if (!list_empty(&c->clean_list)) {
719c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from clean_list to GC next\n");
721da177e4SLinus Torvalds 		nextlist = &c->clean_list;
731da177e4SLinus Torvalds 	} else if (!list_empty(&c->dirty_list)) {
749c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from dirty_list to GC next (clean_list was empty)\n");
751da177e4SLinus Torvalds 
761da177e4SLinus Torvalds 		nextlist = &c->dirty_list;
771da177e4SLinus Torvalds 	} else if (!list_empty(&c->very_dirty_list)) {
789c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n");
791da177e4SLinus Torvalds 		nextlist = &c->very_dirty_list;
801da177e4SLinus Torvalds 	} else if (!list_empty(&c->erasable_list)) {
819c261b33SJoe Perches 		jffs2_dbg(1, "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n");
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds 		nextlist = &c->erasable_list;
84a42163d7SArtem B. Bityuckiy 	} else if (!list_empty(&c->erasable_pending_wbuf_list)) {
85a42163d7SArtem B. Bityuckiy 		/* There are blocks are wating for the wbuf sync */
869c261b33SJoe Perches 		jffs2_dbg(1, "Synching wbuf in order to reuse erasable_pending_wbuf_list blocks\n");
873cceb9f6SArtem B. Bityuckiy 		spin_unlock(&c->erase_completion_lock);
88a42163d7SArtem B. Bityuckiy 		jffs2_flush_wbuf_pad(c);
893cceb9f6SArtem B. Bityuckiy 		spin_lock(&c->erase_completion_lock);
90a42163d7SArtem B. Bityuckiy 		goto again;
911da177e4SLinus Torvalds 	} else {
921da177e4SLinus Torvalds 		/* Eep. All were empty */
935a528957SJoe Perches 		jffs2_dbg(1, "No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n");
941da177e4SLinus Torvalds 		return NULL;
951da177e4SLinus Torvalds 	}
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds 	ret = list_entry(nextlist->next, struct jffs2_eraseblock, list);
981da177e4SLinus Torvalds 	list_del(&ret->list);
991da177e4SLinus Torvalds 	c->gcblock = ret;
1001da177e4SLinus Torvalds 	ret->gc_node = ret->first_node;
1011da177e4SLinus Torvalds 	if (!ret->gc_node) {
102da320f05SJoe Perches 		pr_warn("Eep. ret->gc_node for block at 0x%08x is NULL\n",
103da320f05SJoe Perches 			ret->offset);
1041da177e4SLinus Torvalds 		BUG();
1051da177e4SLinus Torvalds 	}
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 	/* Have we accidentally picked a clean block with wasted space ? */
1081da177e4SLinus Torvalds 	if (ret->wasted_size) {
1099c261b33SJoe Perches 		jffs2_dbg(1, "Converting wasted_size %08x to dirty_size\n",
1109c261b33SJoe Perches 			  ret->wasted_size);
1111da177e4SLinus Torvalds 		ret->dirty_size += ret->wasted_size;
1121da177e4SLinus Torvalds 		c->wasted_size -= ret->wasted_size;
1131da177e4SLinus Torvalds 		c->dirty_size += ret->wasted_size;
1141da177e4SLinus Torvalds 		ret->wasted_size = 0;
1151da177e4SLinus Torvalds 	}
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds 	return ret;
1181da177e4SLinus Torvalds }
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds /* jffs2_garbage_collect_pass
1211da177e4SLinus Torvalds  * Make a single attempt to progress GC. Move one node, and possibly
1221da177e4SLinus Torvalds  * start erasing one eraseblock.
1231da177e4SLinus Torvalds  */
jffs2_garbage_collect_pass(struct jffs2_sb_info * c)1241da177e4SLinus Torvalds int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
1251da177e4SLinus Torvalds {
1261da177e4SLinus Torvalds 	struct jffs2_inode_info *f;
1271da177e4SLinus Torvalds 	struct jffs2_inode_cache *ic;
1281da177e4SLinus Torvalds 	struct jffs2_eraseblock *jeb;
1291da177e4SLinus Torvalds 	struct jffs2_raw_node_ref *raw;
1302665ea84SDavid Woodhouse 	uint32_t gcblock_dirty;
1311da177e4SLinus Torvalds 	int ret = 0, inum, nlink;
132aa98d7cfSKaiGai Kohei 	int xattr = 0;
1331da177e4SLinus Torvalds 
134ced22070SDavid Woodhouse 	if (mutex_lock_interruptible(&c->alloc_sem))
1351da177e4SLinus Torvalds 		return -EINTR;
1361da177e4SLinus Torvalds 
1375817b9dcSDavid Woodhouse 
1381da177e4SLinus Torvalds 	for (;;) {
1395817b9dcSDavid Woodhouse 		/* We can't start doing GC until we've finished checking
1405817b9dcSDavid Woodhouse 		   the node CRCs etc. */
1415817b9dcSDavid Woodhouse 		int bucket, want_ino;
1425817b9dcSDavid Woodhouse 
1431da177e4SLinus Torvalds 		spin_lock(&c->erase_completion_lock);
1441da177e4SLinus Torvalds 		if (!c->unchecked_size)
1451da177e4SLinus Torvalds 			break;
1461da177e4SLinus Torvalds 		spin_unlock(&c->erase_completion_lock);
1471da177e4SLinus Torvalds 
148aa98d7cfSKaiGai Kohei 		if (!xattr)
149aa98d7cfSKaiGai Kohei 			xattr = jffs2_verify_xattr(c);
150aa98d7cfSKaiGai Kohei 
1511da177e4SLinus Torvalds 		spin_lock(&c->inocache_lock);
1525817b9dcSDavid Woodhouse 		/* Instead of doing the inodes in numeric order, doing a lookup
1535817b9dcSDavid Woodhouse 		 * in the hash for each possible number, just walk the hash
1545817b9dcSDavid Woodhouse 		 * buckets of *existing* inodes. This means that we process
1555817b9dcSDavid Woodhouse 		 * them out-of-order, but it can be a lot faster if there's
1565817b9dcSDavid Woodhouse 		 * a sparse inode# space. Which there often is. */
1575817b9dcSDavid Woodhouse 		want_ino = c->check_ino;
1585817b9dcSDavid Woodhouse 		for (bucket = c->check_ino % c->inocache_hashsize ; bucket < c->inocache_hashsize; bucket++) {
1595817b9dcSDavid Woodhouse 			for (ic = c->inocache_list[bucket]; ic; ic = ic->next) {
1605817b9dcSDavid Woodhouse 				if (ic->ino < want_ino)
1611da177e4SLinus Torvalds 					continue;
1625817b9dcSDavid Woodhouse 
1635817b9dcSDavid Woodhouse 				if (ic->state != INO_STATE_CHECKEDABSENT &&
1645817b9dcSDavid Woodhouse 				    ic->state != INO_STATE_PRESENT)
1655817b9dcSDavid Woodhouse 					goto got_next; /* with inocache_lock held */
1665817b9dcSDavid Woodhouse 
1675817b9dcSDavid Woodhouse 				jffs2_dbg(1, "Skipping ino #%u already checked\n",
1685817b9dcSDavid Woodhouse 					  ic->ino);
1691da177e4SLinus Torvalds 			}
1705817b9dcSDavid Woodhouse 			want_ino = 0;
1715817b9dcSDavid Woodhouse 		}
1725817b9dcSDavid Woodhouse 
1735817b9dcSDavid Woodhouse 		/* Point c->check_ino past the end of the last bucket. */
1745817b9dcSDavid Woodhouse 		c->check_ino = ((c->highest_ino + c->inocache_hashsize + 1) &
1755817b9dcSDavid Woodhouse 				~c->inocache_hashsize) - 1;
1765817b9dcSDavid Woodhouse 
1775817b9dcSDavid Woodhouse 		spin_unlock(&c->inocache_lock);
1785817b9dcSDavid Woodhouse 
1795817b9dcSDavid Woodhouse 		pr_crit("Checked all inodes but still 0x%x bytes of unchecked space?\n",
1805817b9dcSDavid Woodhouse 			c->unchecked_size);
1815817b9dcSDavid Woodhouse 		jffs2_dbg_dump_block_lists_nolock(c);
1825817b9dcSDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
1835817b9dcSDavid Woodhouse 		return -ENOSPC;
1845817b9dcSDavid Woodhouse 
1855817b9dcSDavid Woodhouse 	got_next:
1865817b9dcSDavid Woodhouse 		/* For next time round the loop, we want c->checked_ino to indicate
1875817b9dcSDavid Woodhouse 		 * the *next* one we want to check. And since we're walking the
1885817b9dcSDavid Woodhouse 		 * buckets rather than doing it sequentially, it's: */
1895817b9dcSDavid Woodhouse 		c->check_ino = ic->ino + c->inocache_hashsize;
1901da177e4SLinus Torvalds 
19127c72b04SDavid Woodhouse 		if (!ic->pino_nlink) {
1929c261b33SJoe Perches 			jffs2_dbg(1, "Skipping check of ino #%d with nlink/pino zero\n",
1939c261b33SJoe Perches 				  ic->ino);
1941da177e4SLinus Torvalds 			spin_unlock(&c->inocache_lock);
195355ed4e1SKaiGai Kohei 			jffs2_xattr_delete_inode(c, ic);
1961da177e4SLinus Torvalds 			continue;
1971da177e4SLinus Torvalds 		}
1981da177e4SLinus Torvalds 		switch(ic->state) {
1991da177e4SLinus Torvalds 		case INO_STATE_CHECKEDABSENT:
2001da177e4SLinus Torvalds 		case INO_STATE_PRESENT:
2011da177e4SLinus Torvalds 			spin_unlock(&c->inocache_lock);
2021da177e4SLinus Torvalds 			continue;
2031da177e4SLinus Torvalds 
2041da177e4SLinus Torvalds 		case INO_STATE_GC:
2051da177e4SLinus Torvalds 		case INO_STATE_CHECKING:
206da320f05SJoe Perches 			pr_warn("Inode #%u is in state %d during CRC check phase!\n",
207da320f05SJoe Perches 				ic->ino, ic->state);
2081da177e4SLinus Torvalds 			spin_unlock(&c->inocache_lock);
2091da177e4SLinus Torvalds 			BUG();
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 		case INO_STATE_READING:
2121da177e4SLinus Torvalds 			/* We need to wait for it to finish, lest we move on
2131da177e4SLinus Torvalds 			   and trigger the BUG() above while we haven't yet
2141da177e4SLinus Torvalds 			   finished checking all its nodes */
2159c261b33SJoe Perches 			jffs2_dbg(1, "Waiting for ino #%u to finish reading\n",
2169c261b33SJoe Perches 				  ic->ino);
217d96fb997SDavid Woodhouse 			/* We need to come back again for the _same_ inode. We've
218d96fb997SDavid Woodhouse 			 made no progress in this case, but that should be OK */
2195817b9dcSDavid Woodhouse 			c->check_ino = ic->ino;
220d96fb997SDavid Woodhouse 
221ced22070SDavid Woodhouse 			mutex_unlock(&c->alloc_sem);
2221da177e4SLinus Torvalds 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
2231da177e4SLinus Torvalds 			return 0;
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds 		default:
2261da177e4SLinus Torvalds 			BUG();
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds 		case INO_STATE_UNCHECKED:
2291da177e4SLinus Torvalds 			;
2301da177e4SLinus Torvalds 		}
2311da177e4SLinus Torvalds 		ic->state = INO_STATE_CHECKING;
2321da177e4SLinus Torvalds 		spin_unlock(&c->inocache_lock);
2331da177e4SLinus Torvalds 
2349c261b33SJoe Perches 		jffs2_dbg(1, "%s(): triggering inode scan of ino#%u\n",
2359c261b33SJoe Perches 			  __func__, ic->ino);
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds 		ret = jffs2_do_crccheck_inode(c, ic);
2381da177e4SLinus Torvalds 		if (ret)
239da320f05SJoe Perches 			pr_warn("Returned error for crccheck of ino #%u. Expect badness...\n",
240da320f05SJoe Perches 				ic->ino);
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
243ced22070SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
2441da177e4SLinus Torvalds 		return ret;
2451da177e4SLinus Torvalds 	}
2461da177e4SLinus Torvalds 
2470717bf84SDavid Woodhouse 	/* If there are any blocks which need erasing, erase them now */
2480717bf84SDavid Woodhouse 	if (!list_empty(&c->erase_complete_list) ||
2490717bf84SDavid Woodhouse 	    !list_empty(&c->erase_pending_list)) {
2500717bf84SDavid Woodhouse 		spin_unlock(&c->erase_completion_lock);
2510717bf84SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
2529c261b33SJoe Perches 		jffs2_dbg(1, "%s(): erasing pending blocks\n", __func__);
25381cfc9f1SJoakim Tjernlund 		if (jffs2_erase_pending_blocks(c, 1))
2540717bf84SDavid Woodhouse 			return 0;
25581cfc9f1SJoakim Tjernlund 
2569c261b33SJoe Perches 		jffs2_dbg(1, "No progress from erasing block; doing GC anyway\n");
25781cfc9f1SJoakim Tjernlund 		mutex_lock(&c->alloc_sem);
258226bb7dfSJosh Cartwright 		spin_lock(&c->erase_completion_lock);
2590717bf84SDavid Woodhouse 	}
2600717bf84SDavid Woodhouse 
2611da177e4SLinus Torvalds 	/* First, work out which block we're garbage-collecting */
2621da177e4SLinus Torvalds 	jeb = c->gcblock;
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds 	if (!jeb)
2651da177e4SLinus Torvalds 		jeb = jffs2_find_gc_block(c);
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds 	if (!jeb) {
268422b1202SDavid Woodhouse 		/* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */
2690717bf84SDavid Woodhouse 		if (c->nr_erasing_blocks) {
270422b1202SDavid Woodhouse 			spin_unlock(&c->erase_completion_lock);
271422b1202SDavid Woodhouse 			mutex_unlock(&c->alloc_sem);
272422b1202SDavid Woodhouse 			return -EAGAIN;
273422b1202SDavid Woodhouse 		}
2745a528957SJoe Perches 		jffs2_dbg(1, "Couldn't find erase block to garbage collect!\n");
2751da177e4SLinus Torvalds 		spin_unlock(&c->erase_completion_lock);
276ced22070SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
2771da177e4SLinus Torvalds 		return -EIO;
2781da177e4SLinus Torvalds 	}
2791da177e4SLinus Torvalds 
2809c261b33SJoe Perches 	jffs2_dbg(1, "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n",
2819c261b33SJoe Perches 		  jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
2821da177e4SLinus Torvalds 	D1(if (c->nextblock)
2831da177e4SLinus Torvalds 	   printk(KERN_DEBUG "Nextblock at  %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size));
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds 	if (!jeb->used_size) {
286ced22070SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
2871da177e4SLinus Torvalds 		goto eraseit;
2881da177e4SLinus Torvalds 	}
2891da177e4SLinus Torvalds 
2901da177e4SLinus Torvalds 	raw = jeb->gc_node;
2912665ea84SDavid Woodhouse 	gcblock_dirty = jeb->dirty_size;
2921da177e4SLinus Torvalds 
2931da177e4SLinus Torvalds 	while(ref_obsolete(raw)) {
2949c261b33SJoe Perches 		jffs2_dbg(1, "Node at 0x%08x is obsolete... skipping\n",
2959c261b33SJoe Perches 			  ref_offset(raw));
29699988f7bSDavid Woodhouse 		raw = ref_next(raw);
2971da177e4SLinus Torvalds 		if (unlikely(!raw)) {
298da320f05SJoe Perches 			pr_warn("eep. End of raw list while still supposedly nodes to GC\n");
299da320f05SJoe Perches 			pr_warn("erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
300da320f05SJoe Perches 				jeb->offset, jeb->free_size,
301da320f05SJoe Perches 				jeb->dirty_size, jeb->used_size);
3021da177e4SLinus Torvalds 			jeb->gc_node = raw;
3031da177e4SLinus Torvalds 			spin_unlock(&c->erase_completion_lock);
304ced22070SDavid Woodhouse 			mutex_unlock(&c->alloc_sem);
3051da177e4SLinus Torvalds 			BUG();
3061da177e4SLinus Torvalds 		}
3071da177e4SLinus Torvalds 	}
3081da177e4SLinus Torvalds 	jeb->gc_node = raw;
3091da177e4SLinus Torvalds 
3109c261b33SJoe Perches 	jffs2_dbg(1, "Going to garbage collect node at 0x%08x\n",
3119c261b33SJoe Perches 		  ref_offset(raw));
3121da177e4SLinus Torvalds 
3131da177e4SLinus Torvalds 	if (!raw->next_in_ino) {
3141da177e4SLinus Torvalds 		/* Inode-less node. Clean marker, snapshot or something like that */
3151da177e4SLinus Torvalds 		spin_unlock(&c->erase_completion_lock);
3166171586aSDavid Woodhouse 		if (ref_flags(raw) == REF_PRISTINE) {
3176171586aSDavid Woodhouse 			/* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */
3186171586aSDavid Woodhouse 			jffs2_garbage_collect_pristine(c, NULL, raw);
3196171586aSDavid Woodhouse 		} else {
3206171586aSDavid Woodhouse 			/* Just mark it obsolete */
3211da177e4SLinus Torvalds 			jffs2_mark_node_obsolete(c, raw);
3226171586aSDavid Woodhouse 		}
323ced22070SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
3241da177e4SLinus Torvalds 		goto eraseit_lock;
3251da177e4SLinus Torvalds 	}
3261da177e4SLinus Torvalds 
3271da177e4SLinus Torvalds 	ic = jffs2_raw_ref_to_ic(raw);
3281da177e4SLinus Torvalds 
329084702e0SKaiGai Kohei #ifdef CONFIG_JFFS2_FS_XATTR
330aa98d7cfSKaiGai Kohei 	/* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr.
331084702e0SKaiGai Kohei 	 * We can decide whether this node is inode or xattr by ic->class.     */
332084702e0SKaiGai Kohei 	if (ic->class == RAWNODE_CLASS_XATTR_DATUM
333084702e0SKaiGai Kohei 	    || ic->class == RAWNODE_CLASS_XATTR_REF) {
334084702e0SKaiGai Kohei 		spin_unlock(&c->erase_completion_lock);
335084702e0SKaiGai Kohei 
336084702e0SKaiGai Kohei 		if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
337c9f700f8SKaiGai Kohei 			ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw);
338084702e0SKaiGai Kohei 		} else {
339c9f700f8SKaiGai Kohei 			ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
340084702e0SKaiGai Kohei 		}
3412665ea84SDavid Woodhouse 		goto test_gcnode;
342084702e0SKaiGai Kohei 	}
343084702e0SKaiGai Kohei #endif
344aa98d7cfSKaiGai Kohei 
3451da177e4SLinus Torvalds 	/* We need to hold the inocache. Either the erase_completion_lock or
3461da177e4SLinus Torvalds 	   the inocache_lock are sufficient; we trade down since the inocache_lock
3471da177e4SLinus Torvalds 	   causes less contention. */
3481da177e4SLinus Torvalds 	spin_lock(&c->inocache_lock);
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds 	spin_unlock(&c->erase_completion_lock);
3511da177e4SLinus Torvalds 
3529c261b33SJoe Perches 	jffs2_dbg(1, "%s(): collecting from block @0x%08x. Node @0x%08x(%d), ino #%u\n",
3539c261b33SJoe Perches 		  __func__, jeb->offset, ref_offset(raw), ref_flags(raw),
3549c261b33SJoe Perches 		  ic->ino);
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds 	/* Three possibilities:
3571da177e4SLinus Torvalds 	   1. Inode is already in-core. We must iget it and do proper
3581da177e4SLinus Torvalds 	      updating to its fragtree, etc.
3591da177e4SLinus Torvalds 	   2. Inode is not in-core, node is REF_PRISTINE. We lock the
3601da177e4SLinus Torvalds 	      inocache to prevent a read_inode(), copy the node intact.
3611da177e4SLinus Torvalds 	   3. Inode is not in-core, node is not pristine. We must iget()
3621da177e4SLinus Torvalds 	      and take the slow path.
3631da177e4SLinus Torvalds 	*/
3641da177e4SLinus Torvalds 
3651da177e4SLinus Torvalds 	switch(ic->state) {
3661da177e4SLinus Torvalds 	case INO_STATE_CHECKEDABSENT:
3671da177e4SLinus Torvalds 		/* It's been checked, but it's not currently in-core.
3681da177e4SLinus Torvalds 		   We can just copy any pristine nodes, but have
3691da177e4SLinus Torvalds 		   to prevent anyone else from doing read_inode() while
3701da177e4SLinus Torvalds 		   we're at it, so we set the state accordingly */
3711da177e4SLinus Torvalds 		if (ref_flags(raw) == REF_PRISTINE)
3721da177e4SLinus Torvalds 			ic->state = INO_STATE_GC;
3731da177e4SLinus Torvalds 		else {
3749c261b33SJoe Perches 			jffs2_dbg(1, "Ino #%u is absent but node not REF_PRISTINE. Reading.\n",
3759c261b33SJoe Perches 				  ic->ino);
3761da177e4SLinus Torvalds 		}
3771da177e4SLinus Torvalds 		break;
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds 	case INO_STATE_PRESENT:
3801da177e4SLinus Torvalds 		/* It's in-core. GC must iget() it. */
3811da177e4SLinus Torvalds 		break;
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	case INO_STATE_UNCHECKED:
3841da177e4SLinus Torvalds 	case INO_STATE_CHECKING:
3851da177e4SLinus Torvalds 	case INO_STATE_GC:
3861da177e4SLinus Torvalds 		/* Should never happen. We should have finished checking
3871da177e4SLinus Torvalds 		   by the time we actually start doing any GC, and since
3881da177e4SLinus Torvalds 		   we're holding the alloc_sem, no other garbage collection
3891da177e4SLinus Torvalds 		   can happen.
3901da177e4SLinus Torvalds 		*/
391da320f05SJoe Perches 		pr_crit("Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
3921da177e4SLinus Torvalds 			ic->ino, ic->state);
393ced22070SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
3941da177e4SLinus Torvalds 		spin_unlock(&c->inocache_lock);
3951da177e4SLinus Torvalds 		BUG();
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 	case INO_STATE_READING:
3981da177e4SLinus Torvalds 		/* Someone's currently trying to read it. We must wait for
3991da177e4SLinus Torvalds 		   them to finish and then go through the full iget() route
4001da177e4SLinus Torvalds 		   to do the GC. However, sometimes read_inode() needs to get
4011da177e4SLinus Torvalds 		   the alloc_sem() (for marking nodes invalid) so we must
4021da177e4SLinus Torvalds 		   drop the alloc_sem before sleeping. */
4031da177e4SLinus Torvalds 
404ced22070SDavid Woodhouse 		mutex_unlock(&c->alloc_sem);
4059c261b33SJoe Perches 		jffs2_dbg(1, "%s(): waiting for ino #%u in state %d\n",
4069c261b33SJoe Perches 			  __func__, ic->ino, ic->state);
4071da177e4SLinus Torvalds 		sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
4081da177e4SLinus Torvalds 		/* And because we dropped the alloc_sem we must start again from the
4091da177e4SLinus Torvalds 		   beginning. Ponder chance of livelock here -- we're returning success
4101da177e4SLinus Torvalds 		   without actually making any progress.
4111da177e4SLinus Torvalds 
4121da177e4SLinus Torvalds 		   Q: What are the chances that the inode is back in INO_STATE_READING
4131da177e4SLinus Torvalds 		   again by the time we next enter this function? And that this happens
4141da177e4SLinus Torvalds 		   enough times to cause a real delay?
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 		   A: Small enough that I don't care :)
4171da177e4SLinus Torvalds 		*/
4181da177e4SLinus Torvalds 		return 0;
4191da177e4SLinus Torvalds 	}
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds 	/* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the
4221da177e4SLinus Torvalds 	   node intact, and we don't have to muck about with the fragtree etc.
4231da177e4SLinus Torvalds 	   because we know it's not in-core. If it _was_ in-core, we go through
4241da177e4SLinus Torvalds 	   all the iget() crap anyway */
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds 	if (ic->state == INO_STATE_GC) {
4271da177e4SLinus Torvalds 		spin_unlock(&c->inocache_lock);
4281da177e4SLinus Torvalds 
4291da177e4SLinus Torvalds 		ret = jffs2_garbage_collect_pristine(c, ic, raw);
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds 		spin_lock(&c->inocache_lock);
4321da177e4SLinus Torvalds 		ic->state = INO_STATE_CHECKEDABSENT;
4331da177e4SLinus Torvalds 		wake_up(&c->inocache_wq);
4341da177e4SLinus Torvalds 
4351da177e4SLinus Torvalds 		if (ret != -EBADFD) {
4361da177e4SLinus Torvalds 			spin_unlock(&c->inocache_lock);
4372665ea84SDavid Woodhouse 			goto test_gcnode;
4381da177e4SLinus Torvalds 		}
4391da177e4SLinus Torvalds 
4401da177e4SLinus Torvalds 		/* Fall through if it wanted us to, with inocache_lock held */
4411da177e4SLinus Torvalds 	}
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds 	/* Prevent the fairly unlikely race where the gcblock is
4441da177e4SLinus Torvalds 	   entirely obsoleted by the final close of a file which had
4451da177e4SLinus Torvalds 	   the only valid nodes in the block, followed by erasure,
4461da177e4SLinus Torvalds 	   followed by freeing of the ic because the erased block(s)
4471da177e4SLinus Torvalds 	   held _all_ the nodes of that inode.... never been seen but
4481da177e4SLinus Torvalds 	   it's vaguely possible. */
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 	inum = ic->ino;
45127c72b04SDavid Woodhouse 	nlink = ic->pino_nlink;
4521da177e4SLinus Torvalds 	spin_unlock(&c->inocache_lock);
4531da177e4SLinus Torvalds 
4541b690b48SDavid Woodhouse 	f = jffs2_gc_fetch_inode(c, inum, !nlink);
4551da177e4SLinus Torvalds 	if (IS_ERR(f)) {
4561da177e4SLinus Torvalds 		ret = PTR_ERR(f);
4571da177e4SLinus Torvalds 		goto release_sem;
4581da177e4SLinus Torvalds 	}
4591da177e4SLinus Torvalds 	if (!f) {
4601da177e4SLinus Torvalds 		ret = 0;
4611da177e4SLinus Torvalds 		goto release_sem;
4621da177e4SLinus Torvalds 	}
4631da177e4SLinus Torvalds 
4641da177e4SLinus Torvalds 	ret = jffs2_garbage_collect_live(c, jeb, raw, f);
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds 	jffs2_gc_release_inode(c, f);
4671da177e4SLinus Torvalds 
4682665ea84SDavid Woodhouse  test_gcnode:
4692665ea84SDavid Woodhouse 	if (jeb->dirty_size == gcblock_dirty && !ref_obsolete(jeb->gc_node)) {
4702665ea84SDavid Woodhouse 		/* Eep. This really should never happen. GC is broken */
471da320f05SJoe Perches 		pr_err("Error garbage collecting node at %08x!\n",
472da320f05SJoe Perches 		       ref_offset(jeb->gc_node));
4732665ea84SDavid Woodhouse 		ret = -ENOSPC;
4744fc8a607SDavid Woodhouse 	}
4751da177e4SLinus Torvalds  release_sem:
476ced22070SDavid Woodhouse 	mutex_unlock(&c->alloc_sem);
4771da177e4SLinus Torvalds 
4781da177e4SLinus Torvalds  eraseit_lock:
4791da177e4SLinus Torvalds 	/* If we've finished this block, start it erasing */
4801da177e4SLinus Torvalds 	spin_lock(&c->erase_completion_lock);
4811da177e4SLinus Torvalds 
4821da177e4SLinus Torvalds  eraseit:
4831da177e4SLinus Torvalds 	if (c->gcblock && !c->gcblock->used_size) {
4849c261b33SJoe Perches 		jffs2_dbg(1, "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n",
4859c261b33SJoe Perches 			  c->gcblock->offset);
4861da177e4SLinus Torvalds 		/* We're GC'ing an empty block? */
4871da177e4SLinus Torvalds 		list_add_tail(&c->gcblock->list, &c->erase_pending_list);
4881da177e4SLinus Torvalds 		c->gcblock = NULL;
4891da177e4SLinus Torvalds 		c->nr_erasing_blocks++;
490ae3b6ba0SDavid Woodhouse 		jffs2_garbage_collect_trigger(c);
4911da177e4SLinus Torvalds 	}
4921da177e4SLinus Torvalds 	spin_unlock(&c->erase_completion_lock);
4931da177e4SLinus Torvalds 
4941da177e4SLinus Torvalds 	return ret;
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds 
jffs2_garbage_collect_live(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb,struct jffs2_raw_node_ref * raw,struct jffs2_inode_info * f)4971da177e4SLinus Torvalds static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_eraseblock *jeb,
4981da177e4SLinus Torvalds 				      struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f)
4991da177e4SLinus Torvalds {
5001da177e4SLinus Torvalds 	struct jffs2_node_frag *frag;
5011da177e4SLinus Torvalds 	struct jffs2_full_dnode *fn = NULL;
5021da177e4SLinus Torvalds 	struct jffs2_full_dirent *fd;
5031da177e4SLinus Torvalds 	uint32_t start = 0, end = 0, nrfrags = 0;
5041da177e4SLinus Torvalds 	int ret = 0;
5051da177e4SLinus Torvalds 
506ced22070SDavid Woodhouse 	mutex_lock(&f->sem);
5071da177e4SLinus Torvalds 
5081da177e4SLinus Torvalds 	/* Now we have the lock for this inode. Check that it's still the one at the head
5091da177e4SLinus Torvalds 	   of the list. */
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds 	spin_lock(&c->erase_completion_lock);
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds 	if (c->gcblock != jeb) {
5141da177e4SLinus Torvalds 		spin_unlock(&c->erase_completion_lock);
5159c261b33SJoe Perches 		jffs2_dbg(1, "GC block is no longer gcblock. Restart\n");
5161da177e4SLinus Torvalds 		goto upnout;
5171da177e4SLinus Torvalds 	}
5181da177e4SLinus Torvalds 	if (ref_obsolete(raw)) {
5191da177e4SLinus Torvalds 		spin_unlock(&c->erase_completion_lock);
5209c261b33SJoe Perches 		jffs2_dbg(1, "node to be GC'd was obsoleted in the meantime.\n");
5211da177e4SLinus Torvalds 		/* They'll call again */
5221da177e4SLinus Torvalds 		goto upnout;
5231da177e4SLinus Torvalds 	}
5241da177e4SLinus Torvalds 	spin_unlock(&c->erase_completion_lock);
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 	/* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */
5271da177e4SLinus Torvalds 	if (f->metadata && f->metadata->raw == raw) {
5281da177e4SLinus Torvalds 		fn = f->metadata;
5291da177e4SLinus Torvalds 		ret = jffs2_garbage_collect_metadata(c, jeb, f, fn);
5301da177e4SLinus Torvalds 		goto upnout;
5311da177e4SLinus Torvalds 	}
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds 	/* FIXME. Read node and do lookup? */
5341da177e4SLinus Torvalds 	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
5351da177e4SLinus Torvalds 		if (frag->node && frag->node->raw == raw) {
5361da177e4SLinus Torvalds 			fn = frag->node;
5371da177e4SLinus Torvalds 			end = frag->ofs + frag->size;
5381da177e4SLinus Torvalds 			if (!nrfrags++)
5391da177e4SLinus Torvalds 				start = frag->ofs;
5401da177e4SLinus Torvalds 			if (nrfrags == frag->node->frags)
5411da177e4SLinus Torvalds 				break; /* We've found them all */
5421da177e4SLinus Torvalds 		}
5431da177e4SLinus Torvalds 	}
5441da177e4SLinus Torvalds 	if (fn) {
5451da177e4SLinus Torvalds 		if (ref_flags(raw) == REF_PRISTINE) {
5461da177e4SLinus Torvalds 			ret = jffs2_garbage_collect_pristine(c, f->inocache, raw);
5471da177e4SLinus Torvalds 			if (!ret) {
5481da177e4SLinus Torvalds 				/* Urgh. Return it sensibly. */
5491da177e4SLinus Torvalds 				frag->node->raw = f->inocache->nodes;
5501da177e4SLinus Torvalds 			}
5511da177e4SLinus Torvalds 			if (ret != -EBADFD)
5521da177e4SLinus Torvalds 				goto upnout;
5531da177e4SLinus Torvalds 		}
5541da177e4SLinus Torvalds 		/* We found a datanode. Do the GC */
55509cbfeafSKirill A. Shutemov 		if((start >> PAGE_SHIFT) < ((end-1) >> PAGE_SHIFT)) {
5561da177e4SLinus Torvalds 			/* It crosses a page boundary. Therefore, it must be a hole. */
5571da177e4SLinus Torvalds 			ret = jffs2_garbage_collect_hole(c, jeb, f, fn, start, end);
5581da177e4SLinus Torvalds 		} else {
5591da177e4SLinus Torvalds 			/* It could still be a hole. But we GC the page this way anyway */
5601da177e4SLinus Torvalds 			ret = jffs2_garbage_collect_dnode(c, jeb, f, fn, start, end);
5611da177e4SLinus Torvalds 		}
5621da177e4SLinus Torvalds 		goto upnout;
5631da177e4SLinus Torvalds 	}
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds 	/* Wasn't a dnode. Try dirent */
5661da177e4SLinus Torvalds 	for (fd = f->dents; fd; fd=fd->next) {
5671da177e4SLinus Torvalds 		if (fd->raw == raw)
5681da177e4SLinus Torvalds 			break;
5691da177e4SLinus Torvalds 	}
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds 	if (fd && fd->ino) {
5721da177e4SLinus Torvalds 		ret = jffs2_garbage_collect_dirent(c, jeb, f, fd);
5731da177e4SLinus Torvalds 	} else if (fd) {
5741da177e4SLinus Torvalds 		ret = jffs2_garbage_collect_deletion_dirent(c, jeb, f, fd);
5751da177e4SLinus Torvalds 	} else {
576da320f05SJoe Perches 		pr_warn("Raw node at 0x%08x wasn't in node lists for ino #%u\n",
5771da177e4SLinus Torvalds 			ref_offset(raw), f->inocache->ino);
5781da177e4SLinus Torvalds 		if (ref_obsolete(raw)) {
579da320f05SJoe Perches 			pr_warn("But it's obsolete so we don't mind too much\n");
5801da177e4SLinus Torvalds 		} else {
581e0c8e42fSArtem B. Bityutskiy 			jffs2_dbg_dump_node(c, ref_offset(raw));
582e0c8e42fSArtem B. Bityutskiy 			BUG();
5831da177e4SLinus Torvalds 		}
5841da177e4SLinus Torvalds 	}
5851da177e4SLinus Torvalds  upnout:
586ced22070SDavid Woodhouse 	mutex_unlock(&f->sem);
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds 	return ret;
5891da177e4SLinus Torvalds }
5901da177e4SLinus Torvalds 
jffs2_garbage_collect_pristine(struct jffs2_sb_info * c,struct jffs2_inode_cache * ic,struct jffs2_raw_node_ref * raw)5911da177e4SLinus Torvalds static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
5921da177e4SLinus Torvalds 					  struct jffs2_inode_cache *ic,
5931da177e4SLinus Torvalds 					  struct jffs2_raw_node_ref *raw)
5941da177e4SLinus Torvalds {
5951da177e4SLinus Torvalds 	union jffs2_node_union *node;
5961da177e4SLinus Torvalds 	size_t retlen;
5971da177e4SLinus Torvalds 	int ret;
5981da177e4SLinus Torvalds 	uint32_t phys_ofs, alloclen;
5991da177e4SLinus Torvalds 	uint32_t crc, rawlen;
6001da177e4SLinus Torvalds 	int retried = 0;
6011da177e4SLinus Torvalds 
6029c261b33SJoe Perches 	jffs2_dbg(1, "Going to GC REF_PRISTINE node at 0x%08x\n",
6039c261b33SJoe Perches 		  ref_offset(raw));
6041da177e4SLinus Torvalds 
6056171586aSDavid Woodhouse 	alloclen = rawlen = ref_totlen(c, c->gcblock, raw);
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds 	/* Ask for a small amount of space (or the totlen if smaller) because we
6081da177e4SLinus Torvalds 	   don't want to force wastage of the end of a block if splitting would
6091da177e4SLinus Torvalds 	   work. */
6106171586aSDavid Woodhouse 	if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
6116171586aSDavid Woodhouse 		alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN;
6126171586aSDavid Woodhouse 
6139fe4854cSDavid Woodhouse 	ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen);
6146171586aSDavid Woodhouse 	/* 'rawlen' is not the exact summary size; it is only an upper estimation */
615e631ddbaSFerenc Havasi 
6161da177e4SLinus Torvalds 	if (ret)
6171da177e4SLinus Torvalds 		return ret;
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 	if (alloclen < rawlen) {
6201da177e4SLinus Torvalds 		/* Doesn't fit untouched. We'll go the old route and split it */
6211da177e4SLinus Torvalds 		return -EBADFD;
6221da177e4SLinus Torvalds 	}
6231da177e4SLinus Torvalds 
6241da177e4SLinus Torvalds 	node = kmalloc(rawlen, GFP_KERNEL);
6251da177e4SLinus Torvalds 	if (!node)
6261da177e4SLinus Torvalds 		return -ENOMEM;
6271da177e4SLinus Torvalds 
6281da177e4SLinus Torvalds 	ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node);
6291da177e4SLinus Torvalds 	if (!ret && retlen != rawlen)
6301da177e4SLinus Torvalds 		ret = -EIO;
6311da177e4SLinus Torvalds 	if (ret)
6321da177e4SLinus Torvalds 		goto out_node;
6331da177e4SLinus Torvalds 
6341da177e4SLinus Torvalds 	crc = crc32(0, node, sizeof(struct jffs2_unknown_node)-4);
6351da177e4SLinus Torvalds 	if (je32_to_cpu(node->u.hdr_crc) != crc) {
636da320f05SJoe Perches 		pr_warn("Header CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
6371da177e4SLinus Torvalds 			ref_offset(raw), je32_to_cpu(node->u.hdr_crc), crc);
6381da177e4SLinus Torvalds 		goto bail;
6391da177e4SLinus Torvalds 	}
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 	switch(je16_to_cpu(node->u.nodetype)) {
6421da177e4SLinus Torvalds 	case JFFS2_NODETYPE_INODE:
6431da177e4SLinus Torvalds 		crc = crc32(0, node, sizeof(node->i)-8);
6441da177e4SLinus Torvalds 		if (je32_to_cpu(node->i.node_crc) != crc) {
645da320f05SJoe Perches 			pr_warn("Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
646da320f05SJoe Perches 				ref_offset(raw), je32_to_cpu(node->i.node_crc),
647da320f05SJoe Perches 				crc);
6481da177e4SLinus Torvalds 			goto bail;
6491da177e4SLinus Torvalds 		}
6501da177e4SLinus Torvalds 
6511da177e4SLinus Torvalds 		if (je32_to_cpu(node->i.dsize)) {
6521da177e4SLinus Torvalds 			crc = crc32(0, node->i.data, je32_to_cpu(node->i.csize));
6531da177e4SLinus Torvalds 			if (je32_to_cpu(node->i.data_crc) != crc) {
654da320f05SJoe Perches 				pr_warn("Data CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
655da320f05SJoe Perches 					ref_offset(raw),
656da320f05SJoe Perches 					je32_to_cpu(node->i.data_crc), crc);
6571da177e4SLinus Torvalds 				goto bail;
6581da177e4SLinus Torvalds 			}
6591da177e4SLinus Torvalds 		}
6601da177e4SLinus Torvalds 		break;
6611da177e4SLinus Torvalds 
6621da177e4SLinus Torvalds 	case JFFS2_NODETYPE_DIRENT:
6631da177e4SLinus Torvalds 		crc = crc32(0, node, sizeof(node->d)-8);
6641da177e4SLinus Torvalds 		if (je32_to_cpu(node->d.node_crc) != crc) {
665da320f05SJoe Perches 			pr_warn("Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
666da320f05SJoe Perches 				ref_offset(raw),
667da320f05SJoe Perches 				je32_to_cpu(node->d.node_crc), crc);
6681da177e4SLinus Torvalds 			goto bail;
6691da177e4SLinus Torvalds 		}
6701da177e4SLinus Torvalds 
671b534e70cSDavid Woodhouse 		if (strnlen(node->d.name, node->d.nsize) != node->d.nsize) {
672da320f05SJoe Perches 			pr_warn("Name in dirent node at 0x%08x contains zeroes\n",
673da320f05SJoe Perches 				ref_offset(raw));
674b534e70cSDavid Woodhouse 			goto bail;
675b534e70cSDavid Woodhouse 		}
676b534e70cSDavid Woodhouse 
6771da177e4SLinus Torvalds 		if (node->d.nsize) {
6781da177e4SLinus Torvalds 			crc = crc32(0, node->d.name, node->d.nsize);
6791da177e4SLinus Torvalds 			if (je32_to_cpu(node->d.name_crc) != crc) {
680da320f05SJoe Perches 				pr_warn("Name CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
681da320f05SJoe Perches 					ref_offset(raw),
682da320f05SJoe Perches 					je32_to_cpu(node->d.name_crc), crc);
6831da177e4SLinus Torvalds 				goto bail;
6841da177e4SLinus Torvalds 			}
6851da177e4SLinus Torvalds 		}
6861da177e4SLinus Torvalds 		break;
6871da177e4SLinus Torvalds 	default:
6886171586aSDavid Woodhouse 		/* If it's inode-less, we don't _know_ what it is. Just copy it intact */
6896171586aSDavid Woodhouse 		if (ic) {
690da320f05SJoe Perches 			pr_warn("Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
6911da177e4SLinus Torvalds 				ref_offset(raw), je16_to_cpu(node->u.nodetype));
6921da177e4SLinus Torvalds 			goto bail;
6931da177e4SLinus Torvalds 		}
6946171586aSDavid Woodhouse 	}
6951da177e4SLinus Torvalds 
6961da177e4SLinus Torvalds 	/* OK, all the CRCs are good; this node can just be copied as-is. */
6971da177e4SLinus Torvalds  retry:
6982f785402SDavid Woodhouse 	phys_ofs = write_ofs(c);
6991da177e4SLinus Torvalds 
7001da177e4SLinus Torvalds 	ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
7011da177e4SLinus Torvalds 
7021da177e4SLinus Torvalds 	if (ret || (retlen != rawlen)) {
703da320f05SJoe Perches 		pr_notice("Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
7042f785402SDavid Woodhouse 			  rawlen, phys_ofs, ret, retlen);
7051da177e4SLinus Torvalds 		if (retlen) {
7062f785402SDavid Woodhouse 			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
7071da177e4SLinus Torvalds 		} else {
708da320f05SJoe Perches 			pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n",
709da320f05SJoe Perches 				  phys_ofs);
7101da177e4SLinus Torvalds 		}
7112f785402SDavid Woodhouse 		if (!retried) {
7121da177e4SLinus Torvalds 			/* Try to reallocate space and retry */
7131da177e4SLinus Torvalds 			uint32_t dummy;
7141da177e4SLinus Torvalds 			struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
7151da177e4SLinus Torvalds 
7161da177e4SLinus Torvalds 			retried = 1;
7171da177e4SLinus Torvalds 
7189c261b33SJoe Perches 			jffs2_dbg(1, "Retrying failed write of REF_PRISTINE node.\n");
7191da177e4SLinus Torvalds 
720730554d9SArtem B. Bityutskiy 			jffs2_dbg_acct_sanity_check(c,jeb);
721730554d9SArtem B. Bityutskiy 			jffs2_dbg_acct_paranoia_check(c, jeb);
7221da177e4SLinus Torvalds 
7239fe4854cSDavid Woodhouse 			ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen);
724e631ddbaSFerenc Havasi 						/* this is not the exact summary size of it,
725e631ddbaSFerenc Havasi 							it is only an upper estimation */
7261da177e4SLinus Torvalds 
7271da177e4SLinus Torvalds 			if (!ret) {
7289c261b33SJoe Perches 				jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write.\n",
7299c261b33SJoe Perches 					  phys_ofs);
7301da177e4SLinus Torvalds 
731730554d9SArtem B. Bityutskiy 				jffs2_dbg_acct_sanity_check(c,jeb);
732730554d9SArtem B. Bityutskiy 				jffs2_dbg_acct_paranoia_check(c, jeb);
7331da177e4SLinus Torvalds 
7341da177e4SLinus Torvalds 				goto retry;
7351da177e4SLinus Torvalds 			}
7369c261b33SJoe Perches 			jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n",
7379c261b33SJoe Perches 				  ret);
7381da177e4SLinus Torvalds 		}
7391da177e4SLinus Torvalds 
7401da177e4SLinus Torvalds 		if (!ret)
7411da177e4SLinus Torvalds 			ret = -EIO;
7421da177e4SLinus Torvalds 		goto out_node;
7431da177e4SLinus Torvalds 	}
7442f785402SDavid Woodhouse 	jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
7451da177e4SLinus Torvalds 
7461da177e4SLinus Torvalds 	jffs2_mark_node_obsolete(c, raw);
7479c261b33SJoe Perches 	jffs2_dbg(1, "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n",
7489c261b33SJoe Perches 		  ref_offset(raw));
7491da177e4SLinus Torvalds 
7501da177e4SLinus Torvalds  out_node:
7511da177e4SLinus Torvalds 	kfree(node);
7521da177e4SLinus Torvalds 	return ret;
7531da177e4SLinus Torvalds  bail:
7541da177e4SLinus Torvalds 	ret = -EBADFD;
7551da177e4SLinus Torvalds 	goto out_node;
7561da177e4SLinus Torvalds }
7571da177e4SLinus Torvalds 
jffs2_garbage_collect_metadata(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb,struct jffs2_inode_info * f,struct jffs2_full_dnode * fn)7581da177e4SLinus Torvalds static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
7591da177e4SLinus Torvalds 					struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
7601da177e4SLinus Torvalds {
7611da177e4SLinus Torvalds 	struct jffs2_full_dnode *new_fn;
7621da177e4SLinus Torvalds 	struct jffs2_raw_inode ri;
7638557fd51SArtem B. Bityuckiy 	struct jffs2_node_frag *last_frag;
764aef9ab47SDavid Woodhouse 	union jffs2_device_node dev;
7652e16cfcaSDavid Woodhouse 	char *mdata = NULL;
7662e16cfcaSDavid Woodhouse 	int mdatalen = 0;
7679fe4854cSDavid Woodhouse 	uint32_t alloclen, ilen;
7681da177e4SLinus Torvalds 	int ret;
7691da177e4SLinus Torvalds 
7701da177e4SLinus Torvalds 	if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
7711da177e4SLinus Torvalds 	    S_ISCHR(JFFS2_F_I_MODE(f)) ) {
7721da177e4SLinus Torvalds 		/* For these, we don't actually need to read the old node */
773aef9ab47SDavid Woodhouse 		mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
7741da177e4SLinus Torvalds 		mdata = (char *)&dev;
7759c261b33SJoe Perches 		jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n",
7769c261b33SJoe Perches 			  __func__, mdatalen);
7771da177e4SLinus Torvalds 	} else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
7781da177e4SLinus Torvalds 		mdatalen = fn->size;
7791da177e4SLinus Torvalds 		mdata = kmalloc(fn->size, GFP_KERNEL);
7801da177e4SLinus Torvalds 		if (!mdata) {
781da320f05SJoe Perches 			pr_warn("kmalloc of mdata failed in jffs2_garbage_collect_metadata()\n");
7821da177e4SLinus Torvalds 			return -ENOMEM;
7831da177e4SLinus Torvalds 		}
7841da177e4SLinus Torvalds 		ret = jffs2_read_dnode(c, f, fn, mdata, 0, mdatalen);
7851da177e4SLinus Torvalds 		if (ret) {
786da320f05SJoe Perches 			pr_warn("read of old metadata failed in jffs2_garbage_collect_metadata(): %d\n",
787da320f05SJoe Perches 				ret);
7881da177e4SLinus Torvalds 			kfree(mdata);
7891da177e4SLinus Torvalds 			return ret;
7901da177e4SLinus Torvalds 		}
7919c261b33SJoe Perches 		jffs2_dbg(1, "%s(): Writing %d bites of symlink target\n",
7929c261b33SJoe Perches 			  __func__, mdatalen);
7931da177e4SLinus Torvalds 
7941da177e4SLinus Torvalds 	}
7951da177e4SLinus Torvalds 
7969fe4854cSDavid Woodhouse 	ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen,
797e631ddbaSFerenc Havasi 				JFFS2_SUMMARY_INODE_SIZE);
7981da177e4SLinus Torvalds 	if (ret) {
799da320f05SJoe Perches 		pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n",
8001da177e4SLinus Torvalds 			sizeof(ri) + mdatalen, ret);
8011da177e4SLinus Torvalds 		goto out;
8021da177e4SLinus Torvalds 	}
8031da177e4SLinus Torvalds 
8048557fd51SArtem B. Bityuckiy 	last_frag = frag_last(&f->fragtree);
8058557fd51SArtem B. Bityuckiy 	if (last_frag)
8068557fd51SArtem B. Bityuckiy 		/* Fetch the inode length from the fragtree rather then
8078557fd51SArtem B. Bityuckiy 		 * from i_size since i_size may have not been updated yet */
8088557fd51SArtem B. Bityuckiy 		ilen = last_frag->ofs + last_frag->size;
8098557fd51SArtem B. Bityuckiy 	else
8108557fd51SArtem B. Bityuckiy 		ilen = JFFS2_F_I_SIZE(f);
8118557fd51SArtem B. Bityuckiy 
8121da177e4SLinus Torvalds 	memset(&ri, 0, sizeof(ri));
8131da177e4SLinus Torvalds 	ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
8141da177e4SLinus Torvalds 	ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
8151da177e4SLinus Torvalds 	ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen);
8161da177e4SLinus Torvalds 	ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds 	ri.ino = cpu_to_je32(f->inocache->ino);
8191da177e4SLinus Torvalds 	ri.version = cpu_to_je32(++f->highest_version);
8201da177e4SLinus Torvalds 	ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
8211da177e4SLinus Torvalds 	ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
8221da177e4SLinus Torvalds 	ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
8238557fd51SArtem B. Bityuckiy 	ri.isize = cpu_to_je32(ilen);
8241da177e4SLinus Torvalds 	ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
8251da177e4SLinus Torvalds 	ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
8261da177e4SLinus Torvalds 	ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
8271da177e4SLinus Torvalds 	ri.offset = cpu_to_je32(0);
8281da177e4SLinus Torvalds 	ri.csize = cpu_to_je32(mdatalen);
8291da177e4SLinus Torvalds 	ri.dsize = cpu_to_je32(mdatalen);
8301da177e4SLinus Torvalds 	ri.compr = JFFS2_COMPR_NONE;
8311da177e4SLinus Torvalds 	ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
8321da177e4SLinus Torvalds 	ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
8331da177e4SLinus Torvalds 
8349fe4854cSDavid Woodhouse 	new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC);
8351da177e4SLinus Torvalds 
8361da177e4SLinus Torvalds 	if (IS_ERR(new_fn)) {
837da320f05SJoe Perches 		pr_warn("Error writing new dnode: %ld\n", PTR_ERR(new_fn));
8381da177e4SLinus Torvalds 		ret = PTR_ERR(new_fn);
8391da177e4SLinus Torvalds 		goto out;
8401da177e4SLinus Torvalds 	}
8411da177e4SLinus Torvalds 	jffs2_mark_node_obsolete(c, fn->raw);
8421da177e4SLinus Torvalds 	jffs2_free_full_dnode(fn);
8431da177e4SLinus Torvalds 	f->metadata = new_fn;
8441da177e4SLinus Torvalds  out:
8451da177e4SLinus Torvalds 	if (S_ISLNK(JFFS2_F_I_MODE(f)))
8461da177e4SLinus Torvalds 		kfree(mdata);
8471da177e4SLinus Torvalds 	return ret;
8481da177e4SLinus Torvalds }
8491da177e4SLinus Torvalds 
jffs2_garbage_collect_dirent(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb,struct jffs2_inode_info * f,struct jffs2_full_dirent * fd)8501da177e4SLinus Torvalds static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
8511da177e4SLinus Torvalds 					struct jffs2_inode_info *f, struct jffs2_full_dirent *fd)
8521da177e4SLinus Torvalds {
8531da177e4SLinus Torvalds 	struct jffs2_full_dirent *new_fd;
8541da177e4SLinus Torvalds 	struct jffs2_raw_dirent rd;
8559fe4854cSDavid Woodhouse 	uint32_t alloclen;
8561da177e4SLinus Torvalds 	int ret;
8571da177e4SLinus Torvalds 
8581da177e4SLinus Torvalds 	rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
8591da177e4SLinus Torvalds 	rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
8601da177e4SLinus Torvalds 	rd.nsize = strlen(fd->name);
8611da177e4SLinus Torvalds 	rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize);
8621da177e4SLinus Torvalds 	rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4));
8631da177e4SLinus Torvalds 
8641da177e4SLinus Torvalds 	rd.pino = cpu_to_je32(f->inocache->ino);
8651da177e4SLinus Torvalds 	rd.version = cpu_to_je32(++f->highest_version);
8661da177e4SLinus Torvalds 	rd.ino = cpu_to_je32(fd->ino);
8673a69e0cdSArtem B. Bityutskiy 	/* If the times on this inode were set by explicit utime() they can be different,
8683a69e0cdSArtem B. Bityutskiy 	   so refrain from splatting them. */
8693a69e0cdSArtem B. Bityutskiy 	if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f))
8703a69e0cdSArtem B. Bityutskiy 		rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f));
8713a69e0cdSArtem B. Bityutskiy 	else
8723a69e0cdSArtem B. Bityutskiy 		rd.mctime = cpu_to_je32(0);
8731da177e4SLinus Torvalds 	rd.type = fd->type;
8741da177e4SLinus Torvalds 	rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8));
8751da177e4SLinus Torvalds 	rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize));
8761da177e4SLinus Torvalds 
8779fe4854cSDavid Woodhouse 	ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen,
878e631ddbaSFerenc Havasi 				JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize));
8791da177e4SLinus Torvalds 	if (ret) {
880da320f05SJoe Perches 		pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n",
8811da177e4SLinus Torvalds 			sizeof(rd)+rd.nsize, ret);
8821da177e4SLinus Torvalds 		return ret;
8831da177e4SLinus Torvalds 	}
8849fe4854cSDavid Woodhouse 	new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC);
8851da177e4SLinus Torvalds 
8861da177e4SLinus Torvalds 	if (IS_ERR(new_fd)) {
887da320f05SJoe Perches 		pr_warn("jffs2_write_dirent in garbage_collect_dirent failed: %ld\n",
888da320f05SJoe Perches 			PTR_ERR(new_fd));
8891da177e4SLinus Torvalds 		return PTR_ERR(new_fd);
8901da177e4SLinus Torvalds 	}
8911da177e4SLinus Torvalds 	jffs2_add_fd_to_list(c, new_fd, &f->dents);
8921da177e4SLinus Torvalds 	return 0;
8931da177e4SLinus Torvalds }
8941da177e4SLinus Torvalds 
jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb,struct jffs2_inode_info * f,struct jffs2_full_dirent * fd)8951da177e4SLinus Torvalds static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
8961da177e4SLinus Torvalds 					struct jffs2_inode_info *f, struct jffs2_full_dirent *fd)
8971da177e4SLinus Torvalds {
8981da177e4SLinus Torvalds 	struct jffs2_full_dirent **fdp = &f->dents;
8991da177e4SLinus Torvalds 	int found = 0;
9001da177e4SLinus Torvalds 
9011da177e4SLinus Torvalds 	/* On a medium where we can't actually mark nodes obsolete
9021da177e4SLinus Torvalds 	   pernamently, such as NAND flash, we need to work out
9031da177e4SLinus Torvalds 	   whether this deletion dirent is still needed to actively
9041da177e4SLinus Torvalds 	   delete a 'real' dirent with the same name that's still
9051da177e4SLinus Torvalds 	   somewhere else on the flash. */
9061da177e4SLinus Torvalds 	if (!jffs2_can_mark_obsolete(c)) {
9071da177e4SLinus Torvalds 		struct jffs2_raw_dirent *rd;
9081da177e4SLinus Torvalds 		struct jffs2_raw_node_ref *raw;
9091da177e4SLinus Torvalds 		int ret;
9101da177e4SLinus Torvalds 		size_t retlen;
9111da177e4SLinus Torvalds 		int name_len = strlen(fd->name);
9121da177e4SLinus Torvalds 		uint32_t name_crc = crc32(0, fd->name, name_len);
9131da177e4SLinus Torvalds 		uint32_t rawlen = ref_totlen(c, jeb, fd->raw);
9141da177e4SLinus Torvalds 
9151da177e4SLinus Torvalds 		rd = kmalloc(rawlen, GFP_KERNEL);
9161da177e4SLinus Torvalds 		if (!rd)
9171da177e4SLinus Torvalds 			return -ENOMEM;
9181da177e4SLinus Torvalds 
9191da177e4SLinus Torvalds 		/* Prevent the erase code from nicking the obsolete node refs while
9201da177e4SLinus Torvalds 		   we're looking at them. I really don't like this extra lock but
9211da177e4SLinus Torvalds 		   can't see any alternative. Suggestions on a postcard to... */
922ced22070SDavid Woodhouse 		mutex_lock(&c->erase_free_sem);
9231da177e4SLinus Torvalds 
9241da177e4SLinus Torvalds 		for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
9251da177e4SLinus Torvalds 
926aba54da3SArtem Bityutskiy 			cond_resched();
927aba54da3SArtem Bityutskiy 
9281da177e4SLinus Torvalds 			/* We only care about obsolete ones */
9291da177e4SLinus Torvalds 			if (!(ref_obsolete(raw)))
9301da177e4SLinus Torvalds 				continue;
9311da177e4SLinus Torvalds 
9321da177e4SLinus Torvalds 			/* Any dirent with the same name is going to have the same length... */
9331da177e4SLinus Torvalds 			if (ref_totlen(c, NULL, raw) != rawlen)
9341da177e4SLinus Torvalds 				continue;
9351da177e4SLinus Torvalds 
9361da177e4SLinus Torvalds 			/* Doesn't matter if there's one in the same erase block. We're going to
9371da177e4SLinus Torvalds 			   delete it too at the same time. */
9383be36675SAndrew Victor 			if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset))
9391da177e4SLinus Torvalds 				continue;
9401da177e4SLinus Torvalds 
9419c261b33SJoe Perches 			jffs2_dbg(1, "Check potential deletion dirent at %08x\n",
9429c261b33SJoe Perches 				  ref_offset(raw));
9431da177e4SLinus Torvalds 
9441da177e4SLinus Torvalds 			/* This is an obsolete node belonging to the same directory, and it's of the right
9451da177e4SLinus Torvalds 			   length. We need to take a closer look...*/
9461da177e4SLinus Torvalds 			ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd);
9471da177e4SLinus Torvalds 			if (ret) {
948da320f05SJoe Perches 				pr_warn("%s(): Read error (%d) reading obsolete node at %08x\n",
949da320f05SJoe Perches 					__func__, ret, ref_offset(raw));
9501da177e4SLinus Torvalds 				/* If we can't read it, we don't need to continue to obsolete it. Continue */
9511da177e4SLinus Torvalds 				continue;
9521da177e4SLinus Torvalds 			}
9531da177e4SLinus Torvalds 			if (retlen != rawlen) {
954da320f05SJoe Perches 				pr_warn("%s(): Short read (%zd not %u) reading header from obsolete node at %08x\n",
955da320f05SJoe Perches 					__func__, retlen, rawlen,
956da320f05SJoe Perches 					ref_offset(raw));
9571da177e4SLinus Torvalds 				continue;
9581da177e4SLinus Torvalds 			}
9591da177e4SLinus Torvalds 
9601da177e4SLinus Torvalds 			if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT)
9611da177e4SLinus Torvalds 				continue;
9621da177e4SLinus Torvalds 
9631da177e4SLinus Torvalds 			/* If the name CRC doesn't match, skip */
9641da177e4SLinus Torvalds 			if (je32_to_cpu(rd->name_crc) != name_crc)
9651da177e4SLinus Torvalds 				continue;
9661da177e4SLinus Torvalds 
9671da177e4SLinus Torvalds 			/* If the name length doesn't match, or it's another deletion dirent, skip */
9681da177e4SLinus Torvalds 			if (rd->nsize != name_len || !je32_to_cpu(rd->ino))
9691da177e4SLinus Torvalds 				continue;
9701da177e4SLinus Torvalds 
9711da177e4SLinus Torvalds 			/* OK, check the actual name now */
9721da177e4SLinus Torvalds 			if (memcmp(rd->name, fd->name, name_len))
9731da177e4SLinus Torvalds 				continue;
9741da177e4SLinus Torvalds 
9751da177e4SLinus Torvalds 			/* OK. The name really does match. There really is still an older node on
9761da177e4SLinus Torvalds 			   the flash which our deletion dirent obsoletes. So we have to write out
9771da177e4SLinus Torvalds 			   a new deletion dirent to replace it */
978ced22070SDavid Woodhouse 			mutex_unlock(&c->erase_free_sem);
9791da177e4SLinus Torvalds 
9809c261b33SJoe Perches 			jffs2_dbg(1, "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
9819c261b33SJoe Perches 				  ref_offset(fd->raw), fd->name,
9829c261b33SJoe Perches 				  ref_offset(raw), je32_to_cpu(rd->ino));
9831da177e4SLinus Torvalds 			kfree(rd);
9841da177e4SLinus Torvalds 
9851da177e4SLinus Torvalds 			return jffs2_garbage_collect_dirent(c, jeb, f, fd);
9861da177e4SLinus Torvalds 		}
9871da177e4SLinus Torvalds 
988ced22070SDavid Woodhouse 		mutex_unlock(&c->erase_free_sem);
9891da177e4SLinus Torvalds 		kfree(rd);
9901da177e4SLinus Torvalds 	}
9911da177e4SLinus Torvalds 
9923a69e0cdSArtem B. Bityutskiy 	/* FIXME: If we're deleting a dirent which contains the current mtime and ctime,
9933a69e0cdSArtem B. Bityutskiy 	   we should update the metadata node with those times accordingly */
9943a69e0cdSArtem B. Bityutskiy 
9951da177e4SLinus Torvalds 	/* No need for it any more. Just mark it obsolete and remove it from the list */
9961da177e4SLinus Torvalds 	while (*fdp) {
9971da177e4SLinus Torvalds 		if ((*fdp) == fd) {
9981da177e4SLinus Torvalds 			found = 1;
9991da177e4SLinus Torvalds 			*fdp = fd->next;
10001da177e4SLinus Torvalds 			break;
10011da177e4SLinus Torvalds 		}
10021da177e4SLinus Torvalds 		fdp = &(*fdp)->next;
10031da177e4SLinus Torvalds 	}
10041da177e4SLinus Torvalds 	if (!found) {
1005da320f05SJoe Perches 		pr_warn("Deletion dirent \"%s\" not found in list for ino #%u\n",
1006da320f05SJoe Perches 			fd->name, f->inocache->ino);
10071da177e4SLinus Torvalds 	}
10081da177e4SLinus Torvalds 	jffs2_mark_node_obsolete(c, fd->raw);
10091da177e4SLinus Torvalds 	jffs2_free_full_dirent(fd);
10101da177e4SLinus Torvalds 	return 0;
10111da177e4SLinus Torvalds }
10121da177e4SLinus Torvalds 
jffs2_garbage_collect_hole(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb,struct jffs2_inode_info * f,struct jffs2_full_dnode * fn,uint32_t start,uint32_t end)10131da177e4SLinus Torvalds static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
10141da177e4SLinus Torvalds 				      struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
10151da177e4SLinus Torvalds 				      uint32_t start, uint32_t end)
10161da177e4SLinus Torvalds {
10171da177e4SLinus Torvalds 	struct jffs2_raw_inode ri;
10181da177e4SLinus Torvalds 	struct jffs2_node_frag *frag;
10191da177e4SLinus Torvalds 	struct jffs2_full_dnode *new_fn;
10209fe4854cSDavid Woodhouse 	uint32_t alloclen, ilen;
10211da177e4SLinus Torvalds 	int ret;
10221da177e4SLinus Torvalds 
10239c261b33SJoe Perches 	jffs2_dbg(1, "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n",
10249c261b33SJoe Perches 		  f->inocache->ino, start, end);
10251da177e4SLinus Torvalds 
10261da177e4SLinus Torvalds 	memset(&ri, 0, sizeof(ri));
10271da177e4SLinus Torvalds 
10281da177e4SLinus Torvalds 	if(fn->frags > 1) {
10291da177e4SLinus Torvalds 		size_t readlen;
10301da177e4SLinus Torvalds 		uint32_t crc;
10311da177e4SLinus Torvalds 		/* It's partially obsoleted by a later write. So we have to
10321da177e4SLinus Torvalds 		   write it out again with the _same_ version as before */
10331da177e4SLinus Torvalds 		ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri);
10341da177e4SLinus Torvalds 		if (readlen != sizeof(ri) || ret) {
1035da320f05SJoe Perches 			pr_warn("Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %zd. Data will be lost by writing new hole node\n",
1036da320f05SJoe Perches 				ret, readlen);
10371da177e4SLinus Torvalds 			goto fill;
10381da177e4SLinus Torvalds 		}
10391da177e4SLinus Torvalds 		if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) {
1040da320f05SJoe Perches 			pr_warn("%s(): Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n",
1041da320f05SJoe Perches 				__func__, ref_offset(fn->raw),
10421da177e4SLinus Torvalds 				je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE);
10431da177e4SLinus Torvalds 			return -EIO;
10441da177e4SLinus Torvalds 		}
10451da177e4SLinus Torvalds 		if (je32_to_cpu(ri.totlen) != sizeof(ri)) {
1046da320f05SJoe Perches 			pr_warn("%s(): Node at 0x%08x had totlen 0x%x instead of expected 0x%zx\n",
1047da320f05SJoe Perches 				__func__, ref_offset(fn->raw),
10481da177e4SLinus Torvalds 				je32_to_cpu(ri.totlen), sizeof(ri));
10491da177e4SLinus Torvalds 			return -EIO;
10501da177e4SLinus Torvalds 		}
10511da177e4SLinus Torvalds 		crc = crc32(0, &ri, sizeof(ri)-8);
10521da177e4SLinus Torvalds 		if (crc != je32_to_cpu(ri.node_crc)) {
1053da320f05SJoe Perches 			pr_warn("%s: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n",
1054da320f05SJoe Perches 				__func__, ref_offset(fn->raw),
10551da177e4SLinus Torvalds 				je32_to_cpu(ri.node_crc), crc);
10561da177e4SLinus Torvalds 			/* FIXME: We could possibly deal with this by writing new holes for each frag */
1057da320f05SJoe Perches 			pr_warn("Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n",
10581da177e4SLinus Torvalds 				start, end, f->inocache->ino);
10591da177e4SLinus Torvalds 			goto fill;
10601da177e4SLinus Torvalds 		}
10611da177e4SLinus Torvalds 		if (ri.compr != JFFS2_COMPR_ZERO) {
1062da320f05SJoe Perches 			pr_warn("%s(): Node 0x%08x wasn't a hole node!\n",
1063da320f05SJoe Perches 				__func__, ref_offset(fn->raw));
1064da320f05SJoe Perches 			pr_warn("Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n",
10651da177e4SLinus Torvalds 				start, end, f->inocache->ino);
10661da177e4SLinus Torvalds 			goto fill;
10671da177e4SLinus Torvalds 		}
10681da177e4SLinus Torvalds 	} else {
10691da177e4SLinus Torvalds 	fill:
10701da177e4SLinus Torvalds 		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
10711da177e4SLinus Torvalds 		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
10721da177e4SLinus Torvalds 		ri.totlen = cpu_to_je32(sizeof(ri));
10731da177e4SLinus Torvalds 		ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
10741da177e4SLinus Torvalds 
10751da177e4SLinus Torvalds 		ri.ino = cpu_to_je32(f->inocache->ino);
10761da177e4SLinus Torvalds 		ri.version = cpu_to_je32(++f->highest_version);
10771da177e4SLinus Torvalds 		ri.offset = cpu_to_je32(start);
10781da177e4SLinus Torvalds 		ri.dsize = cpu_to_je32(end - start);
10791da177e4SLinus Torvalds 		ri.csize = cpu_to_je32(0);
10801da177e4SLinus Torvalds 		ri.compr = JFFS2_COMPR_ZERO;
10811da177e4SLinus Torvalds 	}
10828557fd51SArtem B. Bityuckiy 
10838557fd51SArtem B. Bityuckiy 	frag = frag_last(&f->fragtree);
10848557fd51SArtem B. Bityuckiy 	if (frag)
10858557fd51SArtem B. Bityuckiy 		/* Fetch the inode length from the fragtree rather then
10868557fd51SArtem B. Bityuckiy 		 * from i_size since i_size may have not been updated yet */
10878557fd51SArtem B. Bityuckiy 		ilen = frag->ofs + frag->size;
10888557fd51SArtem B. Bityuckiy 	else
10898557fd51SArtem B. Bityuckiy 		ilen = JFFS2_F_I_SIZE(f);
10908557fd51SArtem B. Bityuckiy 
10911da177e4SLinus Torvalds 	ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
10921da177e4SLinus Torvalds 	ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
10931da177e4SLinus Torvalds 	ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
10948557fd51SArtem B. Bityuckiy 	ri.isize = cpu_to_je32(ilen);
10951da177e4SLinus Torvalds 	ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
10961da177e4SLinus Torvalds 	ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
10971da177e4SLinus Torvalds 	ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
10981da177e4SLinus Torvalds 	ri.data_crc = cpu_to_je32(0);
10991da177e4SLinus Torvalds 	ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
11001da177e4SLinus Torvalds 
11019fe4854cSDavid Woodhouse 	ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen,
1102e631ddbaSFerenc Havasi 				     JFFS2_SUMMARY_INODE_SIZE);
11031da177e4SLinus Torvalds 	if (ret) {
1104da320f05SJoe Perches 		pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n",
11051da177e4SLinus Torvalds 			sizeof(ri), ret);
11061da177e4SLinus Torvalds 		return ret;
11071da177e4SLinus Torvalds 	}
11089fe4854cSDavid Woodhouse 	new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC);
11091da177e4SLinus Torvalds 
11101da177e4SLinus Torvalds 	if (IS_ERR(new_fn)) {
1111da320f05SJoe Perches 		pr_warn("Error writing new hole node: %ld\n", PTR_ERR(new_fn));
11121da177e4SLinus Torvalds 		return PTR_ERR(new_fn);
11131da177e4SLinus Torvalds 	}
11141da177e4SLinus Torvalds 	if (je32_to_cpu(ri.version) == f->highest_version) {
11151da177e4SLinus Torvalds 		jffs2_add_full_dnode_to_inode(c, f, new_fn);
11161da177e4SLinus Torvalds 		if (f->metadata) {
11171da177e4SLinus Torvalds 			jffs2_mark_node_obsolete(c, f->metadata->raw);
11181da177e4SLinus Torvalds 			jffs2_free_full_dnode(f->metadata);
11191da177e4SLinus Torvalds 			f->metadata = NULL;
11201da177e4SLinus Torvalds 		}
11211da177e4SLinus Torvalds 		return 0;
11221da177e4SLinus Torvalds 	}
11231da177e4SLinus Torvalds 
11241da177e4SLinus Torvalds 	/*
11251da177e4SLinus Torvalds 	 * We should only get here in the case where the node we are
11261da177e4SLinus Torvalds 	 * replacing had more than one frag, so we kept the same version
11271da177e4SLinus Torvalds 	 * number as before. (Except in case of error -- see 'goto fill;'
11281da177e4SLinus Torvalds 	 * above.)
11291da177e4SLinus Torvalds 	 */
11301da177e4SLinus Torvalds 	D1(if(unlikely(fn->frags <= 1)) {
1131da320f05SJoe Perches 			pr_warn("%s(): Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n",
1132da320f05SJoe Perches 				__func__, fn->frags, je32_to_cpu(ri.version),
1133da320f05SJoe Perches 				f->highest_version, je32_to_cpu(ri.ino));
11341da177e4SLinus Torvalds 	});
11351da177e4SLinus Torvalds 
11361da177e4SLinus Torvalds 	/* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */
11371da177e4SLinus Torvalds 	mark_ref_normal(new_fn->raw);
11381da177e4SLinus Torvalds 
11391da177e4SLinus Torvalds 	for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs);
11401da177e4SLinus Torvalds 	     frag; frag = frag_next(frag)) {
11411da177e4SLinus Torvalds 		if (frag->ofs > fn->size + fn->ofs)
11421da177e4SLinus Torvalds 			break;
11431da177e4SLinus Torvalds 		if (frag->node == fn) {
11441da177e4SLinus Torvalds 			frag->node = new_fn;
11451da177e4SLinus Torvalds 			new_fn->frags++;
11461da177e4SLinus Torvalds 			fn->frags--;
11471da177e4SLinus Torvalds 		}
11481da177e4SLinus Torvalds 	}
11491da177e4SLinus Torvalds 	if (fn->frags) {
1150da320f05SJoe Perches 		pr_warn("%s(): Old node still has frags!\n", __func__);
11511da177e4SLinus Torvalds 		BUG();
11521da177e4SLinus Torvalds 	}
11531da177e4SLinus Torvalds 	if (!new_fn->frags) {
1154da320f05SJoe Perches 		pr_warn("%s(): New node has no frags!\n", __func__);
11551da177e4SLinus Torvalds 		BUG();
11561da177e4SLinus Torvalds 	}
11571da177e4SLinus Torvalds 
11581da177e4SLinus Torvalds 	jffs2_mark_node_obsolete(c, fn->raw);
11591da177e4SLinus Torvalds 	jffs2_free_full_dnode(fn);
11601da177e4SLinus Torvalds 
11611da177e4SLinus Torvalds 	return 0;
11621da177e4SLinus Torvalds }
11631da177e4SLinus Torvalds 
jffs2_garbage_collect_dnode(struct jffs2_sb_info * c,struct jffs2_eraseblock * orig_jeb,struct jffs2_inode_info * f,struct jffs2_full_dnode * fn,uint32_t start,uint32_t end)116425dc30b4SDavid Woodhouse static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *orig_jeb,
11651da177e4SLinus Torvalds 				       struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
11661da177e4SLinus Torvalds 				       uint32_t start, uint32_t end)
11671da177e4SLinus Torvalds {
116861b875e8SChristoph Hellwig 	struct inode *inode = OFNI_EDONI_2SFFJ(f);
11691da177e4SLinus Torvalds 	struct jffs2_full_dnode *new_fn;
11701da177e4SLinus Torvalds 	struct jffs2_raw_inode ri;
11719fe4854cSDavid Woodhouse 	uint32_t alloclen, offset, orig_end, orig_start;
11721da177e4SLinus Torvalds 	int ret = 0;
11731da177e4SLinus Torvalds 	unsigned char *comprbuf = NULL, *writebuf;
117461b875e8SChristoph Hellwig 	struct page *page;
11751da177e4SLinus Torvalds 	unsigned char *pg_ptr;
11761da177e4SLinus Torvalds 
11771da177e4SLinus Torvalds 	memset(&ri, 0, sizeof(ri));
11781da177e4SLinus Torvalds 
11799c261b33SJoe Perches 	jffs2_dbg(1, "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n",
11809c261b33SJoe Perches 		  f->inocache->ino, start, end);
11811da177e4SLinus Torvalds 
11821da177e4SLinus Torvalds 	orig_end = end;
11831da177e4SLinus Torvalds 	orig_start = start;
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) {
11861da177e4SLinus Torvalds 		/* Attempt to do some merging. But only expand to cover logically
11871da177e4SLinus Torvalds 		   adjacent frags if the block containing them is already considered
11881da177e4SLinus Torvalds 		   to be dirty. Otherwise we end up with GC just going round in
11891da177e4SLinus Torvalds 		   circles dirtying the nodes it already wrote out, especially
11901da177e4SLinus Torvalds 		   on NAND where we have small eraseblocks and hence a much higher
11911da177e4SLinus Torvalds 		   chance of nodes having to be split to cross boundaries. */
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 		struct jffs2_node_frag *frag;
11941da177e4SLinus Torvalds 		uint32_t min, max;
11951da177e4SLinus Torvalds 
119609cbfeafSKirill A. Shutemov 		min = start & ~(PAGE_SIZE-1);
119709cbfeafSKirill A. Shutemov 		max = min + PAGE_SIZE;
11981da177e4SLinus Torvalds 
11991da177e4SLinus Torvalds 		frag = jffs2_lookup_node_frag(&f->fragtree, start);
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds 		/* BUG_ON(!frag) but that'll happen anyway... */
12021da177e4SLinus Torvalds 
12031da177e4SLinus Torvalds 		BUG_ON(frag->ofs != start);
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds 		/* First grow down... */
12061da177e4SLinus Torvalds 		while((frag = frag_prev(frag)) && frag->ofs >= min) {
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds 			/* If the previous frag doesn't even reach the beginning, there's
12091da177e4SLinus Torvalds 			   excessive fragmentation. Just merge. */
12101da177e4SLinus Torvalds 			if (frag->ofs > min) {
12119c261b33SJoe Perches 				jffs2_dbg(1, "Expanding down to cover partial frag (0x%x-0x%x)\n",
12129c261b33SJoe Perches 					  frag->ofs, frag->ofs+frag->size);
12131da177e4SLinus Torvalds 				start = frag->ofs;
12141da177e4SLinus Torvalds 				continue;
12151da177e4SLinus Torvalds 			}
12161da177e4SLinus Torvalds 			/* OK. This frag holds the first byte of the page. */
12171da177e4SLinus Torvalds 			if (!frag->node || !frag->node->raw) {
12189c261b33SJoe Perches 				jffs2_dbg(1, "First frag in page is hole (0x%x-0x%x). Not expanding down.\n",
12199c261b33SJoe Perches 					  frag->ofs, frag->ofs+frag->size);
12201da177e4SLinus Torvalds 				break;
12211da177e4SLinus Torvalds 			} else {
12221da177e4SLinus Torvalds 
12231da177e4SLinus Torvalds 				/* OK, it's a frag which extends to the beginning of the page. Does it live
12241da177e4SLinus Torvalds 				   in a block which is still considered clean? If so, don't obsolete it.
12251da177e4SLinus Torvalds 				   If not, cover it anyway. */
12261da177e4SLinus Torvalds 
12271da177e4SLinus Torvalds 				struct jffs2_raw_node_ref *raw = frag->node->raw;
12281da177e4SLinus Torvalds 				struct jffs2_eraseblock *jeb;
12291da177e4SLinus Torvalds 
12301da177e4SLinus Torvalds 				jeb = &c->blocks[raw->flash_offset / c->sector_size];
12311da177e4SLinus Torvalds 
12321da177e4SLinus Torvalds 				if (jeb == c->gcblock) {
12339c261b33SJoe Perches 					jffs2_dbg(1, "Expanding down to cover frag (0x%x-0x%x) in gcblock at %08x\n",
12349c261b33SJoe Perches 						  frag->ofs,
12359c261b33SJoe Perches 						  frag->ofs + frag->size,
12369c261b33SJoe Perches 						  ref_offset(raw));
12371da177e4SLinus Torvalds 					start = frag->ofs;
12381da177e4SLinus Torvalds 					break;
12391da177e4SLinus Torvalds 				}
12401da177e4SLinus Torvalds 				if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) {
12419c261b33SJoe Perches 					jffs2_dbg(1, "Not expanding down to cover frag (0x%x-0x%x) in clean block %08x\n",
12429c261b33SJoe Perches 						  frag->ofs,
12439c261b33SJoe Perches 						  frag->ofs + frag->size,
12449c261b33SJoe Perches 						  jeb->offset);
12451da177e4SLinus Torvalds 					break;
12461da177e4SLinus Torvalds 				}
12471da177e4SLinus Torvalds 
12489c261b33SJoe Perches 				jffs2_dbg(1, "Expanding down to cover frag (0x%x-0x%x) in dirty block %08x\n",
12499c261b33SJoe Perches 					  frag->ofs,
12509c261b33SJoe Perches 					  frag->ofs + frag->size,
12519c261b33SJoe Perches 					  jeb->offset);
12521da177e4SLinus Torvalds 				start = frag->ofs;
12531da177e4SLinus Torvalds 				break;
12541da177e4SLinus Torvalds 			}
12551da177e4SLinus Torvalds 		}
12561da177e4SLinus Torvalds 
12571da177e4SLinus Torvalds 		/* ... then up */
12581da177e4SLinus Torvalds 
12591da177e4SLinus Torvalds 		/* Find last frag which is actually part of the node we're to GC. */
12601da177e4SLinus Torvalds 		frag = jffs2_lookup_node_frag(&f->fragtree, end-1);
12611da177e4SLinus Torvalds 
12621da177e4SLinus Torvalds 		while((frag = frag_next(frag)) && frag->ofs+frag->size <= max) {
12631da177e4SLinus Torvalds 
12641da177e4SLinus Torvalds 			/* If the previous frag doesn't even reach the beginning, there's lots
12651da177e4SLinus Torvalds 			   of fragmentation. Just merge. */
12661da177e4SLinus Torvalds 			if (frag->ofs+frag->size < max) {
12679c261b33SJoe Perches 				jffs2_dbg(1, "Expanding up to cover partial frag (0x%x-0x%x)\n",
12689c261b33SJoe Perches 					  frag->ofs, frag->ofs+frag->size);
12691da177e4SLinus Torvalds 				end = frag->ofs + frag->size;
12701da177e4SLinus Torvalds 				continue;
12711da177e4SLinus Torvalds 			}
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 			if (!frag->node || !frag->node->raw) {
12749c261b33SJoe Perches 				jffs2_dbg(1, "Last frag in page is hole (0x%x-0x%x). Not expanding up.\n",
12759c261b33SJoe Perches 					  frag->ofs, frag->ofs+frag->size);
12761da177e4SLinus Torvalds 				break;
12771da177e4SLinus Torvalds 			} else {
12781da177e4SLinus Torvalds 
12791da177e4SLinus Torvalds 				/* OK, it's a frag which extends to the beginning of the page. Does it live
12801da177e4SLinus Torvalds 				   in a block which is still considered clean? If so, don't obsolete it.
12811da177e4SLinus Torvalds 				   If not, cover it anyway. */
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds 				struct jffs2_raw_node_ref *raw = frag->node->raw;
12841da177e4SLinus Torvalds 				struct jffs2_eraseblock *jeb;
12851da177e4SLinus Torvalds 
12861da177e4SLinus Torvalds 				jeb = &c->blocks[raw->flash_offset / c->sector_size];
12871da177e4SLinus Torvalds 
12881da177e4SLinus Torvalds 				if (jeb == c->gcblock) {
12899c261b33SJoe Perches 					jffs2_dbg(1, "Expanding up to cover frag (0x%x-0x%x) in gcblock at %08x\n",
12909c261b33SJoe Perches 						  frag->ofs,
12919c261b33SJoe Perches 						  frag->ofs + frag->size,
12929c261b33SJoe Perches 						  ref_offset(raw));
12931da177e4SLinus Torvalds 					end = frag->ofs + frag->size;
12941da177e4SLinus Torvalds 					break;
12951da177e4SLinus Torvalds 				}
12961da177e4SLinus Torvalds 				if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) {
12979c261b33SJoe Perches 					jffs2_dbg(1, "Not expanding up to cover frag (0x%x-0x%x) in clean block %08x\n",
12989c261b33SJoe Perches 						  frag->ofs,
12999c261b33SJoe Perches 						  frag->ofs + frag->size,
13009c261b33SJoe Perches 						  jeb->offset);
13011da177e4SLinus Torvalds 					break;
13021da177e4SLinus Torvalds 				}
13031da177e4SLinus Torvalds 
13049c261b33SJoe Perches 				jffs2_dbg(1, "Expanding up to cover frag (0x%x-0x%x) in dirty block %08x\n",
13059c261b33SJoe Perches 					  frag->ofs,
13069c261b33SJoe Perches 					  frag->ofs + frag->size,
13079c261b33SJoe Perches 					  jeb->offset);
13081da177e4SLinus Torvalds 				end = frag->ofs + frag->size;
13091da177e4SLinus Torvalds 				break;
13101da177e4SLinus Torvalds 			}
13111da177e4SLinus Torvalds 		}
13129c261b33SJoe Perches 		jffs2_dbg(1, "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n",
13139c261b33SJoe Perches 			  orig_start, orig_end, start, end);
13141da177e4SLinus Torvalds 
13158557fd51SArtem B. Bityuckiy 		D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size));
13161da177e4SLinus Torvalds 		BUG_ON(end < orig_end);
13171da177e4SLinus Torvalds 		BUG_ON(start > orig_start);
13181da177e4SLinus Torvalds 	}
13191da177e4SLinus Torvalds 
132049e91e70SDavid Woodhouse 	/* The rules state that we must obtain the page lock *before* f->sem, so
132149e91e70SDavid Woodhouse 	 * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
132249e91e70SDavid Woodhouse 	 * actually going to *change* so we're safe; we only allow reading.
132349e91e70SDavid Woodhouse 	 *
132449e91e70SDavid Woodhouse 	 * It is important to note that jffs2_write_begin() will ensure that its
132549e91e70SDavid Woodhouse 	 * page is marked Uptodate before allocating space. That means that if we
132649e91e70SDavid Woodhouse 	 * end up here trying to GC the *same* page that jffs2_write_begin() is
132749e91e70SDavid Woodhouse 	 * trying to write out, read_cache_page() will not deadlock. */
132849e91e70SDavid Woodhouse 	mutex_unlock(&f->sem);
132961b875e8SChristoph Hellwig 	page = read_cache_page(inode->i_mapping, start >> PAGE_SHIFT,
1330*e9b5b23eSMatthew Wilcox (Oracle) 			       __jffs2_read_folio, NULL);
133161b875e8SChristoph Hellwig 	if (IS_ERR(page)) {
1332da320f05SJoe Perches 		pr_warn("read_cache_page() returned error: %ld\n",
133361b875e8SChristoph Hellwig 			PTR_ERR(page));
133461b875e8SChristoph Hellwig 		mutex_lock(&f->sem);
133561b875e8SChristoph Hellwig 		return PTR_ERR(page);
13361da177e4SLinus Torvalds 	}
13371da177e4SLinus Torvalds 
133861b875e8SChristoph Hellwig 	pg_ptr = kmap(page);
133961b875e8SChristoph Hellwig 	mutex_lock(&f->sem);
134061b875e8SChristoph Hellwig 
13411da177e4SLinus Torvalds 	offset = start;
13421da177e4SLinus Torvalds 	while(offset < orig_end) {
13431da177e4SLinus Torvalds 		uint32_t datalen;
13441da177e4SLinus Torvalds 		uint32_t cdatalen;
13451da177e4SLinus Torvalds 		uint16_t comprtype = JFFS2_COMPR_NONE;
13461da177e4SLinus Torvalds 
13479fe4854cSDavid Woodhouse 		ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN,
1348e631ddbaSFerenc Havasi 					&alloclen, JFFS2_SUMMARY_INODE_SIZE);
13491da177e4SLinus Torvalds 
13501da177e4SLinus Torvalds 		if (ret) {
1351da320f05SJoe Perches 			pr_warn("jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n",
13521da177e4SLinus Torvalds 				sizeof(ri) + JFFS2_MIN_DATA_LEN, ret);
13531da177e4SLinus Torvalds 			break;
13541da177e4SLinus Torvalds 		}
13551da177e4SLinus Torvalds 		cdatalen = min_t(uint32_t, alloclen - sizeof(ri), end - offset);
13561da177e4SLinus Torvalds 		datalen = end - offset;
13571da177e4SLinus Torvalds 
135809cbfeafSKirill A. Shutemov 		writebuf = pg_ptr + (offset & (PAGE_SIZE -1));
13591da177e4SLinus Torvalds 
13601da177e4SLinus Torvalds 		comprtype = jffs2_compress(c, f, writebuf, &comprbuf, &datalen, &cdatalen);
13611da177e4SLinus Torvalds 
13621da177e4SLinus Torvalds 		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
13631da177e4SLinus Torvalds 		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
13641da177e4SLinus Torvalds 		ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen);
13651da177e4SLinus Torvalds 		ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
13661da177e4SLinus Torvalds 
13671da177e4SLinus Torvalds 		ri.ino = cpu_to_je32(f->inocache->ino);
13681da177e4SLinus Torvalds 		ri.version = cpu_to_je32(++f->highest_version);
13691da177e4SLinus Torvalds 		ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
13701da177e4SLinus Torvalds 		ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
13711da177e4SLinus Torvalds 		ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
13721da177e4SLinus Torvalds 		ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f));
13731da177e4SLinus Torvalds 		ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
13741da177e4SLinus Torvalds 		ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
13751da177e4SLinus Torvalds 		ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
13761da177e4SLinus Torvalds 		ri.offset = cpu_to_je32(offset);
13771da177e4SLinus Torvalds 		ri.csize = cpu_to_je32(cdatalen);
13781da177e4SLinus Torvalds 		ri.dsize = cpu_to_je32(datalen);
13791da177e4SLinus Torvalds 		ri.compr = comprtype & 0xff;
13801da177e4SLinus Torvalds 		ri.usercompr = (comprtype >> 8) & 0xff;
13811da177e4SLinus Torvalds 		ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
13821da177e4SLinus Torvalds 		ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
13831da177e4SLinus Torvalds 
13849fe4854cSDavid Woodhouse 		new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC);
13851da177e4SLinus Torvalds 
13861da177e4SLinus Torvalds 		jffs2_free_comprbuf(comprbuf, writebuf);
13871da177e4SLinus Torvalds 
13881da177e4SLinus Torvalds 		if (IS_ERR(new_fn)) {
1389da320f05SJoe Perches 			pr_warn("Error writing new dnode: %ld\n",
1390da320f05SJoe Perches 				PTR_ERR(new_fn));
13911da177e4SLinus Torvalds 			ret = PTR_ERR(new_fn);
13921da177e4SLinus Torvalds 			break;
13931da177e4SLinus Torvalds 		}
13941da177e4SLinus Torvalds 		ret = jffs2_add_full_dnode_to_inode(c, f, new_fn);
13951da177e4SLinus Torvalds 		offset += datalen;
13961da177e4SLinus Torvalds 		if (f->metadata) {
13971da177e4SLinus Torvalds 			jffs2_mark_node_obsolete(c, f->metadata->raw);
13981da177e4SLinus Torvalds 			jffs2_free_full_dnode(f->metadata);
13991da177e4SLinus Torvalds 			f->metadata = NULL;
14001da177e4SLinus Torvalds 		}
14011da177e4SLinus Torvalds 	}
14021da177e4SLinus Torvalds 
140361b875e8SChristoph Hellwig 	kunmap(page);
140461b875e8SChristoph Hellwig 	put_page(page);
14051da177e4SLinus Torvalds 	return ret;
14061da177e4SLinus Torvalds }
1407