1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7 *
8 * The original JFFS, from which the design for JFFS2 was derived,
9 * was designed and implemented by Axis Communications AB.
10 *
11 * The contents of this file are subject to the Red Hat eCos Public
12 * License Version 1.1 (the "Licence"); you may not use this file
13 * except in compliance with the Licence.  You may obtain a copy of
14 * the Licence at http://www.redhat.com/
15 *
16 * Software distributed under the Licence is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
18 * See the Licence for the specific language governing rights and
19 * limitations under the Licence.
20 *
21 * The Original Code is JFFS2 - Journalling Flash File System, version 2
22 *
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU General Public License version 2 (the "GPL"), in
25 * which case the provisions of the GPL are applicable instead of the
26 * above.  If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use your
28 * version of this file under the RHEPL, indicate your decision by
29 * deleting the provisions above and replace them with the notice and
30 * other provisions required by the GPL.  If you do not delete the
31 * provisions above, a recipient may use your version of this file
32 * under either the RHEPL or the GPL.
33 *
34 * $Id: gc.c,v 1.1.1.1 2008/10/15 03:27:07 james26_jang Exp $
35 *
36 */
37
38#include <linux/kernel.h>
39#include <linux/mtd/mtd.h>
40#include <linux/slab.h>
41#include <linux/jffs2.h>
42#include <linux/sched.h>
43#include <linux/interrupt.h>
44#include <linux/pagemap.h>
45#include "nodelist.h"
46#include "crc32.h"
47
48static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
49					struct inode *inode, struct jffs2_full_dnode *fd);
50static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
51					struct inode *inode, struct jffs2_full_dirent *fd);
52static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
53					struct inode *inode, struct jffs2_full_dirent *fd);
54static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
55				      struct inode *indeo, struct jffs2_full_dnode *fn,
56				      __u32 start, __u32 end);
57static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
58				       struct inode *inode, struct jffs2_full_dnode *fn,
59				       __u32 start, __u32 end);
60
61/* Called with erase_completion_lock held */
62static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)
63{
64	struct jffs2_eraseblock *ret;
65	struct list_head *nextlist = NULL;
66
67	/* Pick an eraseblock to garbage collect next. This is where we'll
68	   put the clever wear-levelling algorithms. Eventually.  */
69	if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) {
70		D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n"));
71		nextlist = &c->bad_used_list;
72	} else if (jiffies % 100 && !list_empty(&c->dirty_list)) {
73		/* Most of the time, pick one off the dirty list */
74		D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n"));
75		nextlist = &c->dirty_list;
76	} else if (!list_empty(&c->clean_list)) {
77		D1(printk(KERN_DEBUG "Picking block from clean_list to GC next\n"));
78		nextlist = &c->clean_list;
79	} else if (!list_empty(&c->dirty_list)) {
80		D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n"));
81
82		nextlist = &c->dirty_list;
83	} else {
84		/* Eep. Both were empty */
85		printk(KERN_NOTICE "jffs2: No clean _or_ dirty blocks to GC from! Where are they all?\n");
86		return NULL;
87	}
88
89	ret = list_entry(nextlist->next, struct jffs2_eraseblock, list);
90	list_del(&ret->list);
91	c->gcblock = ret;
92	ret->gc_node = ret->first_node;
93	if (!ret->gc_node) {
94		printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset);
95		BUG();
96	}
97	return ret;
98}
99
100/* jffs2_garbage_collect_pass
101 * Make a single attempt to progress GC. Move one node, and possibly
102 * start erasing one eraseblock.
103 */
104int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
105{
106	struct jffs2_eraseblock *jeb;
107	struct jffs2_inode_info *f;
108	struct jffs2_raw_node_ref *raw;
109	struct jffs2_node_frag *frag;
110	struct jffs2_full_dnode *fn = NULL;
111	struct jffs2_full_dirent *fd;
112	__u32 start = 0, end = 0, nrfrags = 0;
113	__u32 inum;
114	struct inode *inode;
115	int ret = 0;
116
117	if (down_interruptible(&c->alloc_sem))
118		return -EINTR;
119
120	spin_lock_bh(&c->erase_completion_lock);
121
122	/* First, work out which block we're garbage-collecting */
123	jeb = c->gcblock;
124
125	if (!jeb)
126		jeb = jffs2_find_gc_block(c);
127
128	if (!jeb) {
129		printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n");
130		spin_unlock_bh(&c->erase_completion_lock);
131		up(&c->alloc_sem);
132		return -EIO;
133	}
134
135	D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset));
136
137	if (!jeb->used_size) {
138		up(&c->alloc_sem);
139		goto eraseit;
140	}
141
142	raw = jeb->gc_node;
143
144	while(raw->flash_offset & 1) {
145		D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", raw->flash_offset &~3));
146		jeb->gc_node = raw = raw->next_phys;
147		if (!raw) {
148			printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n");
149			printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
150			       jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);
151			spin_unlock_bh(&c->erase_completion_lock);
152			up(&c->alloc_sem);
153			BUG();
154		}
155	}
156	D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", raw->flash_offset &~3));
157	if (!raw->next_in_ino) {
158		/* Inode-less node. Clean marker, snapshot or something like that */
159		spin_unlock_bh(&c->erase_completion_lock);
160		jffs2_mark_node_obsolete(c, raw);
161		up(&c->alloc_sem);
162		goto eraseit_lock;
163	}
164
165	inum = jffs2_raw_ref_to_inum(raw);
166	D1(printk(KERN_DEBUG "Inode number is #%u\n", inum));
167
168	spin_unlock_bh(&c->erase_completion_lock);
169
170	D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, inum));
171
172	inode = iget(OFNI_BS_2SFFJ(c), inum);
173	if (is_bad_inode(inode)) {
174		printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", inum);
175		/* NB. This will happen again. We need to do something appropriate here. */
176		up(&c->alloc_sem);
177		iput(inode);
178		return -EIO;
179	}
180
181	f = JFFS2_INODE_INFO(inode);
182	down(&f->sem);
183	/* Now we have the lock for this inode. Check that it's still the one at the head
184	   of the list. */
185
186	if (raw->flash_offset & 1) {
187		D1(printk(KERN_DEBUG "node to be GC'd was obsoleted in the meantime.\n"));
188		/* They'll call again */
189		goto upnout;
190	}
191	/* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */
192	if (f->metadata && f->metadata->raw == raw) {
193		fn = f->metadata;
194		ret = jffs2_garbage_collect_metadata(c, jeb, inode, fn);
195		goto upnout;
196	}
197
198	for (frag = f->fraglist; frag; frag = frag->next) {
199		if (frag->node && frag->node->raw == raw) {
200			fn = frag->node;
201			end = frag->ofs + frag->size;
202			if (!nrfrags++)
203				start = frag->ofs;
204			if (nrfrags == frag->node->frags)
205				break; /* We've found them all */
206		}
207	}
208	if (fn) {
209		/* We found a datanode. Do the GC */
210		if((start >> PAGE_CACHE_SHIFT) < ((end-1) >> PAGE_CACHE_SHIFT)) {
211			/* It crosses a page boundary. Therefore, it must be a hole. */
212			ret = jffs2_garbage_collect_hole(c, jeb, inode, fn, start, end);
213		} else {
214			/* It could still be a hole. But we GC the page this way anyway */
215			ret = jffs2_garbage_collect_dnode(c, jeb, inode, fn, start, end);
216		}
217		goto upnout;
218	}
219
220	/* Wasn't a dnode. Try dirent */
221	for (fd = f->dents; fd; fd=fd->next) {
222		if (fd->raw == raw)
223			break;
224	}
225
226	if (fd && fd->ino) {
227		ret = jffs2_garbage_collect_dirent(c, jeb, inode, fd);
228	} else if (fd) {
229		ret = jffs2_garbage_collect_deletion_dirent(c, jeb, inode, fd);
230	} else {
231		printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%lu\n", raw->flash_offset&~3, inode->i_ino);
232		if (raw->flash_offset & 1) {
233			printk(KERN_WARNING "But it's obsolete so we don't mind too much\n");
234		} else {
235			ret = -EIO;
236		}
237	}
238 upnout:
239	up(&f->sem);
240	up(&c->alloc_sem);
241	iput(inode);
242
243 eraseit_lock:
244	/* If we've finished this block, start it erasing */
245	spin_lock_bh(&c->erase_completion_lock);
246
247 eraseit:
248	if (c->gcblock && !c->gcblock->used_size) {
249		D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset));
250		/* We're GC'ing an empty block? */
251		list_add_tail(&c->gcblock->list, &c->erase_pending_list);
252		c->gcblock = NULL;
253		c->nr_erasing_blocks++;
254		jffs2_erase_pending_trigger(c);
255	}
256	spin_unlock_bh(&c->erase_completion_lock);
257
258	return ret;
259}
260
261static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
262					struct inode *inode, struct jffs2_full_dnode *fn)
263{
264	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
265	struct jffs2_full_dnode *new_fn;
266	struct jffs2_raw_inode ri;
267	unsigned short dev;
268	char *mdata = NULL, mdatalen = 0;
269	__u32 alloclen, phys_ofs;
270	int ret;
271
272	if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
273		/* For these, we don't actually need to read the old node */
274		dev =  (MAJOR(to_kdev_t(inode->i_rdev)) << 8) |
275			MINOR(to_kdev_t(inode->i_rdev));
276		mdata = (char *)&dev;
277		mdatalen = sizeof(dev);
278		D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
279	} else if (S_ISLNK(inode->i_mode)) {
280		mdatalen = fn->size;
281		mdata = kmalloc(fn->size, GFP_KERNEL);
282		if (!mdata) {
283			printk(KERN_WARNING "kmalloc of mdata failed in jffs2_garbage_collect_metadata()\n");
284			return -ENOMEM;
285		}
286		ret = jffs2_read_dnode(c, fn, mdata, 0, mdatalen);
287		if (ret) {
288			printk(KERN_WARNING "read of old metadata failed in jffs2_garbage_collect_metadata(): %d\n", ret);
289			kfree(mdata);
290			return ret;
291		}
292		D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bites of symlink target\n", mdatalen));
293
294	}
295
296	ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen);
297	if (ret) {
298		printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_metadata failed: %d\n",
299		       sizeof(ri)+ mdatalen, ret);
300		goto out;
301	}
302
303	memset(&ri, 0, sizeof(ri));
304	ri.magic = JFFS2_MAGIC_BITMASK;
305	ri.nodetype = JFFS2_NODETYPE_INODE;
306	ri.totlen = sizeof(ri) + mdatalen;
307	ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4);
308
309	ri.ino = inode->i_ino;
310	ri.version = ++f->highest_version;
311	ri.mode = inode->i_mode;
312	ri.uid = inode->i_uid;
313	ri.gid = inode->i_gid;
314	ri.isize = inode->i_size;
315	ri.atime = inode->i_atime;
316	ri.ctime = inode->i_ctime;
317	ri.mtime = inode->i_mtime;
318	ri.offset = 0;
319	ri.csize = mdatalen;
320	ri.dsize = mdatalen;
321	ri.compr = JFFS2_COMPR_NONE;
322	ri.node_crc = crc32(0, &ri, sizeof(ri)-8);
323	ri.data_crc = crc32(0, mdata, mdatalen);
324
325	new_fn = jffs2_write_dnode(inode, &ri, mdata, mdatalen, phys_ofs, NULL);
326
327	if (IS_ERR(new_fn)) {
328		printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
329		ret = PTR_ERR(new_fn);
330		goto out;
331	}
332	jffs2_mark_node_obsolete(c, fn->raw);
333	jffs2_free_full_dnode(fn);
334	f->metadata = new_fn;
335 out:
336	if (S_ISLNK(inode->i_mode))
337		kfree(mdata);
338	return ret;
339}
340
341static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
342					struct inode *inode, struct jffs2_full_dirent *fd)
343{
344	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
345	struct jffs2_full_dirent *new_fd;
346	struct jffs2_raw_dirent rd;
347	__u32 alloclen, phys_ofs;
348	int ret;
349
350	rd.magic = JFFS2_MAGIC_BITMASK;
351	rd.nodetype = JFFS2_NODETYPE_DIRENT;
352	rd.nsize = strlen(fd->name);
353	rd.totlen = sizeof(rd) + rd.nsize;
354	rd.hdr_crc = crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4);
355
356	rd.pino = inode->i_ino;
357	rd.version = ++f->highest_version;
358	rd.ino = fd->ino;
359	rd.mctime = max(inode->i_mtime, inode->i_ctime);
360	rd.type = fd->type;
361	rd.node_crc = crc32(0, &rd, sizeof(rd)-8);
362	rd.name_crc = crc32(0, fd->name, rd.nsize);
363
364	ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen);
365	if (ret) {
366		printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dirent failed: %d\n",
367		       sizeof(rd)+rd.nsize, ret);
368		return ret;
369	}
370	new_fd = jffs2_write_dirent(inode, &rd, fd->name, rd.nsize, phys_ofs, NULL);
371
372	if (IS_ERR(new_fd)) {
373		printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd));
374		return PTR_ERR(new_fd);
375	}
376	jffs2_add_fd_to_list(c, new_fd, &f->dents);
377	return 0;
378}
379
380static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
381					struct inode *inode, struct jffs2_full_dirent *fd)
382{
383	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
384	struct jffs2_full_dirent **fdp = &f->dents;
385	int found = 0;
386
387	while (*fdp) {
388		if ((*fdp) == fd) {
389			found = 1;
390			*fdp = fd->next;
391			break;
392		}
393		fdp = &(*fdp)->next;
394	}
395	if (!found) {
396		printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%lu\n", fd->name, inode->i_ino);
397	}
398	jffs2_mark_node_obsolete(c, fd->raw);
399	jffs2_free_full_dirent(fd);
400	return 0;
401}
402
403static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
404				      struct inode *inode, struct jffs2_full_dnode *fn,
405				      __u32 start, __u32 end)
406{
407	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
408	struct jffs2_raw_inode ri;
409	struct jffs2_node_frag *frag;
410	struct jffs2_full_dnode *new_fn;
411	__u32 alloclen, phys_ofs;
412	int ret;
413
414	D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%lu from offset 0x%x to 0x%x\n",
415		  inode->i_ino, start, end));
416
417	memset(&ri, 0, sizeof(ri));
418
419	if(fn->frags > 1) {
420		size_t readlen;
421		__u32 crc;
422		/* It's partially obsoleted by a later write. So we have to
423		   write it out again with the _same_ version as before */
424		ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(ri), &readlen, (char *)&ri);
425		if (readlen != sizeof(ri) || ret) {
426			printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %d. Data will be lost by writing new hold node\n", ret, readlen);
427			goto fill;
428		}
429		if (ri.nodetype != JFFS2_NODETYPE_INODE) {
430			printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n",
431			       fn->raw->flash_offset & ~3, ri.nodetype, JFFS2_NODETYPE_INODE);
432			return -EIO;
433		}
434		if (ri.totlen != sizeof(ri)) {
435			printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%x\n",
436			       fn->raw->flash_offset & ~3, ri.totlen, sizeof(ri));
437			return -EIO;
438		}
439		crc = crc32(0, &ri, sizeof(ri)-8);
440		if (crc != ri.node_crc) {
441			printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n",
442			       fn->raw->flash_offset & ~3, ri.node_crc, crc);
443			printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n",
444			       start, end, inode->i_ino);
445			goto fill;
446		}
447		if (ri.compr != JFFS2_COMPR_ZERO) {
448			printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", fn->raw->flash_offset & ~3);
449			printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n",
450			       start, end, inode->i_ino);
451			goto fill;
452		}
453	} else {
454	fill:
455		ri.magic = JFFS2_MAGIC_BITMASK;
456		ri.nodetype = JFFS2_NODETYPE_INODE;
457		ri.totlen = sizeof(ri);
458		ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4);
459
460		ri.ino = inode->i_ino;
461		ri.version = ++f->highest_version;
462		ri.offset = start;
463		ri.dsize = end - start;
464		ri.csize = 0;
465		ri.compr = JFFS2_COMPR_ZERO;
466	}
467	ri.mode = inode->i_mode;
468	ri.uid = inode->i_uid;
469	ri.gid = inode->i_gid;
470	ri.isize = inode->i_size;
471	ri.atime = inode->i_atime;
472	ri.ctime = inode->i_ctime;
473	ri.mtime = inode->i_mtime;
474	ri.data_crc = 0;
475	ri.node_crc = crc32(0, &ri, sizeof(ri)-8);
476
477	ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen);
478	if (ret) {
479		printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_hole failed: %d\n",
480		       sizeof(ri), ret);
481		return ret;
482	}
483	new_fn = jffs2_write_dnode(inode, &ri, NULL, 0, phys_ofs, NULL);
484
485	if (IS_ERR(new_fn)) {
486		printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn));
487		return PTR_ERR(new_fn);
488	}
489	if (ri.version == f->highest_version) {
490		jffs2_add_full_dnode_to_inode(c, f, new_fn);
491		if (f->metadata) {
492			jffs2_mark_node_obsolete(c, f->metadata->raw);
493			jffs2_free_full_dnode(f->metadata);
494			f->metadata = NULL;
495		}
496		return 0;
497	}
498
499	/*
500	 * We should only get here in the case where the node we are
501	 * replacing had more than one frag, so we kept the same version
502	 * number as before. (Except in case of error -- see 'goto fill;'
503	 * above.)
504	 */
505	D1(if(fn->frags <= 1) {
506		printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n",
507		       fn->frags, ri.version, f->highest_version, ri.ino);
508	});
509
510	for (frag = f->fraglist; frag; frag = frag->next) {
511		if (frag->ofs > fn->size + fn->ofs)
512			break;
513		if (frag->node == fn) {
514			frag->node = new_fn;
515			new_fn->frags++;
516			fn->frags--;
517		}
518	}
519	if (fn->frags) {
520		printk(KERN_WARNING "jffs2_garbage_collect_hole: Old node still has frags!\n");
521		BUG();
522	}
523	if (!new_fn->frags) {
524		printk(KERN_WARNING "jffs2_garbage_collect_hole: New node has no frags!\n");
525		BUG();
526	}
527
528	jffs2_mark_node_obsolete(c, fn->raw);
529	jffs2_free_full_dnode(fn);
530
531	return 0;
532}
533
534static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
535				       struct inode *inode, struct jffs2_full_dnode *fn,
536				       __u32 start, __u32 end)
537{
538	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
539	struct jffs2_full_dnode *new_fn;
540	struct jffs2_raw_inode ri;
541	__u32 alloclen, phys_ofs, offset, orig_end;
542	int ret = 0;
543	unsigned char *comprbuf = NULL, *writebuf;
544	struct page *pg;
545	unsigned char *pg_ptr;
546
547
548	memset(&ri, 0, sizeof(ri));
549
550	D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%lu from offset 0x%x to 0x%x\n",
551		  inode->i_ino, start, end));
552
553	orig_end = end;
554
555
556	/* If we're looking at the last node in the block we're
557	   garbage-collecting, we allow ourselves to merge as if the
558	   block was already erasing. We're likely to be GC'ing a
559	   partial page, and the next block we GC is likely to have
560	   the other half of this page right at the beginning, which
561	   means we'd expand it _then_, as nr_erasing_blocks would have
562	   increased since we checked, and in doing so would obsolete
563	   the partial node which we'd have written here. Meaning that
564	   the GC would churn and churn, and just leave dirty blocks in
565	   it's wake.
566	*/
567	if(c->nr_free_blocks + c->nr_erasing_blocks > JFFS2_RESERVED_BLOCKS_GCMERGE - (fn->raw->next_phys?0:1)) {
568		/* Shitloads of space */
569		start &= ~(PAGE_CACHE_SIZE-1);
570		end = min_t(__u32, start + PAGE_CACHE_SIZE, inode->i_size);
571		D1(printk(KERN_DEBUG "Plenty of free space, so expanding to write from offset 0x%x to 0x%x\n",
572			  start, end));
573		if (end < orig_end) {
574			printk(KERN_WARNING "Eep. jffs2_garbage_collect_dnode extended node to write, but it got smaller: start 0x%x, orig_end 0x%x, end 0x%x\n", start, orig_end, end);
575			end = orig_end;
576		}
577	}
578
579	/* First, use readpage() to read the appropriate page into the page cache */
580	/* Q: What happens if we actually try to GC the _same_ page for which commit_write()
581	 *    triggered garbage collection in the first place?
582	 * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the
583	 *    page OK. We'll actually write it out again in commit_write, which is a little
584	 *    suboptimal, but at least we're correct.
585	 */
586	pg = read_cache_page(inode->i_mapping, start >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode);
587
588	if (IS_ERR(pg)) {
589		printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg));
590		return PTR_ERR(pg);
591	}
592	pg_ptr = (char *)kmap(pg);
593	comprbuf = kmalloc(end - start, GFP_KERNEL);
594
595	offset = start;
596	while(offset < orig_end) {
597		__u32 datalen;
598		__u32 cdatalen;
599		char comprtype = JFFS2_COMPR_NONE;
600
601		ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen);
602
603		if (ret) {
604			printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dnode failed: %d\n",
605			       sizeof(ri)+ JFFS2_MIN_DATA_LEN, ret);
606			break;
607		}
608		cdatalen = min(alloclen - sizeof(ri), end - offset);
609		datalen = end - offset;
610
611		writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1));
612
613		if (comprbuf) {
614			comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen);
615		}
616		if (comprtype) {
617			writebuf = comprbuf;
618		} else {
619			datalen = cdatalen;
620		}
621		ri.magic = JFFS2_MAGIC_BITMASK;
622		ri.nodetype = JFFS2_NODETYPE_INODE;
623		ri.totlen = sizeof(ri) + cdatalen;
624		ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4);
625
626		ri.ino = inode->i_ino;
627		ri.version = ++f->highest_version;
628		ri.mode = inode->i_mode;
629		ri.uid = inode->i_uid;
630		ri.gid = inode->i_gid;
631		ri.isize = inode->i_size;
632		ri.atime = inode->i_atime;
633		ri.ctime = inode->i_ctime;
634		ri.mtime = inode->i_mtime;
635		ri.offset = offset;
636		ri.csize = cdatalen;
637		ri.dsize = datalen;
638		ri.compr = comprtype;
639		ri.node_crc = crc32(0, &ri, sizeof(ri)-8);
640		ri.data_crc = crc32(0, writebuf, cdatalen);
641
642		new_fn = jffs2_write_dnode(inode, &ri, writebuf, cdatalen, phys_ofs, NULL);
643
644		if (IS_ERR(new_fn)) {
645			printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
646			ret = PTR_ERR(new_fn);
647			break;
648		}
649		ret = jffs2_add_full_dnode_to_inode(c, f, new_fn);
650		offset += datalen;
651		if (f->metadata) {
652			jffs2_mark_node_obsolete(c, f->metadata->raw);
653			jffs2_free_full_dnode(f->metadata);
654			f->metadata = NULL;
655		}
656	}
657	if (comprbuf) kfree(comprbuf);
658
659	kunmap(pg);
660	/* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */
661	page_cache_release(pg);
662	return ret;
663}
664
665