[JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code.

As the first step towards eliminating the ref->next_phys member and saving
memory by using an _array_ of struct jffs2_raw_node_ref per eraseblock,
stop the write functions from allocating their own refs; have them just
_reserve_ the appropriate number instead. Then jffs2_link_node_ref() can
just fill them in.

Use a linked list of pre-allocated refs in the superblock, for now. Once
we switch to an array, it'll just be a case of extending that array.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 4616fed..f939f90 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -296,7 +296,7 @@
 			jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
 		/* else it was a non-inode node or already removed, so don't bother */
 
-		jffs2_free_raw_node_ref(ref);
+		__jffs2_free_raw_node_ref(ref);
 	}
 	jeb->last_node = NULL;
 }
@@ -351,7 +351,6 @@
 
 static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
-	struct jffs2_raw_node_ref *marker_ref = NULL;
 	size_t retlen;
 	int ret;
 	uint32_t bad_offset;
@@ -384,11 +383,7 @@
 			.totlen =	cpu_to_je32(c->cleanmarker_size)
 		};
 
-		marker_ref = jffs2_alloc_raw_node_ref();
-		if (!marker_ref) {
-			printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
-			goto refile;
-		}
+		jffs2_prealloc_raw_node_refs(c, 1);
 
 		marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
 
@@ -404,16 +399,13 @@
 				printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
 				       jeb->offset, sizeof(marker), retlen);
 
-			jffs2_free_raw_node_ref(marker_ref);
 			goto filebad;
 		}
 
 		/* Everything else got zeroed before the erase */
 		jeb->free_size = c->sector_size;
-
-		marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-
-		jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
+		/* FIXME Special case for cleanmarker in empty block */
+		jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
 	}
 
 	spin_lock(&c->erase_completion_lock);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index f9e982a..a22ff5d 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -528,7 +528,6 @@
 					  struct jffs2_raw_node_ref *raw)
 {
 	union jffs2_node_union *node;
-	struct jffs2_raw_node_ref *nraw;
 	size_t retlen;
 	int ret;
 	uint32_t phys_ofs, alloclen;
@@ -618,30 +617,21 @@
 		}
 	}
 
-	nraw = jffs2_alloc_raw_node_ref();
-	if (!nraw) {
-		ret = -ENOMEM;
-		goto out_node;
-	}
-
 	/* OK, all the CRCs are good; this node can just be copied as-is. */
  retry:
-	nraw->flash_offset = phys_ofs = write_ofs(c);
+	phys_ofs = write_ofs(c);
 
 	ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
 
 	if (ret || (retlen != rawlen)) {
 		printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
-                       rawlen, nraw->flash_offset, ret, retlen);
+                       rawlen, phys_ofs, ret, retlen);
 		if (retlen) {
-			nraw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, nraw, rawlen, NULL);
-			jffs2_mark_node_obsolete(c, nraw);
+			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
 		} else {
-			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset);
-                        jffs2_free_raw_node_ref(nraw);
+			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
 		}
-		if (!retried && (nraw = jffs2_alloc_raw_node_ref())) {
+		if (!retried) {
 			/* Try to reallocate space and retry */
 			uint32_t dummy;
 			struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
@@ -666,16 +656,13 @@
 				goto retry;
 			}
 			D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-			jffs2_free_raw_node_ref(nraw);
 		}
 
-		jffs2_free_raw_node_ref(nraw);
 		if (!ret)
 			ret = -EIO;
 		goto out_node;
 	}
-	nraw->flash_offset |= REF_PRISTINE;
-	jffs2_add_physical_node_ref(c, nraw, rawlen, ic);
+	jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
 
 	jffs2_mark_node_obsolete(c, raw);
 	D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 272fbea..67529f0 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -26,6 +26,9 @@
 struct jffs2_sb_info {
 	struct mtd_info *mtd;
 
+	struct jffs2_raw_node_ref *refs;
+	int reserved_refs;
+
 	uint32_t highest_ino;
 	uint32_t checked_ino;
 
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index f2473fa..3df3250 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -190,7 +190,29 @@
 	kmem_cache_free(tmp_dnode_info_slab, x);
 }
 
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
+int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr)
+{
+	struct jffs2_raw_node_ref *p = c->refs;
+
+	dbg_memalloc("%d\n", nr);
+
+	while (nr && p) {
+		p = p->next_in_ino;
+		nr--;
+	}
+	while (nr) {
+		p = __jffs2_alloc_raw_node_ref();
+		if (!p)
+			return -ENOMEM;
+		p->next_in_ino = c->refs;
+		c->refs = p;
+		nr--;
+	}
+	c->reserved_refs = nr;
+	return 0;
+}
+
+struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void)
 {
 	struct jffs2_raw_node_ref *ret;
 	ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
@@ -198,7 +220,7 @@
 	return ret;
 }
 
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
+void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
 {
 	dbg_memalloc("%p\n", x);
 	kmem_cache_free(raw_node_ref_slab, x);
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index d25d491..1e6eabd 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -953,13 +953,19 @@
 
 	for (i=0; i<c->nr_blocks; i++) {
 		this = c->blocks[i].first_node;
-		while(this) {
+		while (this) {
 			next = this->next_phys;
-			jffs2_free_raw_node_ref(this);
+			__jffs2_free_raw_node_ref(this);
 			this = next;
 		}
 		c->blocks[i].first_node = c->blocks[i].last_node = NULL;
 	}
+	this = c->refs;
+	while (this) {
+		next = this->next_in_ino;
+		__jffs2_free_raw_node_ref(this);
+		this = next;
+	}
 }
 
 struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset)
@@ -1047,10 +1053,27 @@
 	}
 }
 
-void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-			 struct jffs2_raw_node_ref *ref, uint32_t len,
-			 struct jffs2_inode_cache *ic)
+struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
+					       struct jffs2_eraseblock *jeb,
+					       uint32_t ofs, uint32_t len,
+					       struct jffs2_inode_cache *ic)
 {
+	struct jffs2_raw_node_ref *ref;
+
+	/* These will be preallocated _very_ shortly. */
+	ref = c->refs;
+	if (!c->refs) {
+		JFFS2_WARNING("Using non-preallocated refs!\n");
+		ref = __jffs2_alloc_raw_node_ref();
+		BUG_ON(!ref);
+		WARN_ON(1);
+	} else {
+		c->refs = ref->next_in_ino;
+	}
+
+	ref->next_phys = NULL;
+	ref->flash_offset = ofs;
+
 	if (!jeb->first_node)
 		jeb->first_node = ref;
 	if (jeb->last_node) {
@@ -1093,15 +1116,15 @@
 	c->free_size -= len;
 	jeb->free_size -= len;
 
-	ref->next_phys = NULL;
 #ifdef TEST_TOTLEN
 	/* Set (and test) __totlen field... for now */
 	ref->__totlen = len;
 	ref_totlen(c, jeb, ref);
 #endif
+	return ref;
 }
 
-/* No locking. Do not use on a live file system */
+/* No locking, no reservation of 'ref'. Do not use on a live file system */
 int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 			   uint32_t size)
 {
@@ -1121,18 +1144,10 @@
 		jeb->dirty_size += size;
 		jeb->free_size -= size;
 	} else {
-		struct jffs2_raw_node_ref *ref;
-		ref = jffs2_alloc_raw_node_ref();
-		if (!ref)
-			return -ENOMEM;
+		uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
+		ofs |= REF_OBSOLETE;
 
-		ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
-		ref->flash_offset |= REF_OBSOLETE;
-#ifdef TEST_TOTLEN
-		ref->__totlen = size;
-#endif
-
-		jffs2_link_node_ref(c, jeb, ref, size, NULL);
+		jffs2_link_node_ref(c, jeb, ofs, size, NULL);
 	}
 
 	return 0;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 76f1b94..7cc74d2 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -318,9 +318,10 @@
 int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
 void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
 int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
-void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-			 struct jffs2_raw_node_ref *ref, uint32_t len,
-			 struct jffs2_inode_cache *ic);
+struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
+					       struct jffs2_eraseblock *jeb,
+					       uint32_t ofs, uint32_t len,
+					       struct jffs2_inode_cache *ic);
 extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
 				   struct jffs2_eraseblock *jeb,
 				   struct jffs2_raw_node_ref *ref);
@@ -331,10 +332,9 @@
 			uint32_t *len, int prio, uint32_t sumsize);
 int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
 			uint32_t *len, uint32_t sumsize);
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, 
-				struct jffs2_raw_node_ref *new,
-				uint32_t len,
-				struct jffs2_inode_cache *ic);
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, 
+						       uint32_t ofs, uint32_t len,
+						       struct jffs2_inode_cache *ic);
 void jffs2_complete_reservation(struct jffs2_sb_info *c);
 void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
 
@@ -378,8 +378,9 @@
 void jffs2_free_raw_inode(struct jffs2_raw_inode *);
 struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
 void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void);
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
+int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr);
+struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void);
+void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
 struct jffs2_node_frag *jffs2_alloc_node_frag(void);
 void jffs2_free_node_frag(struct jffs2_node_frag *);
 struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 8feb874..01bf277 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -137,6 +137,8 @@
 		}
 	}
 	spin_unlock(&c->erase_completion_lock);
+	if (!ret)
+		ret = jffs2_prealloc_raw_node_refs(c, 1);
 	if (ret)
 		up(&c->alloc_sem);
 	return ret;
@@ -158,6 +160,9 @@
 		}
 	}
 	spin_unlock(&c->erase_completion_lock);
+	if (!ret)
+		ret = jffs2_prealloc_raw_node_refs(c, 1);
+
 	return ret;
 }
 
@@ -381,30 +386,30 @@
  *	Must be called with the alloc_sem held.
  */
 
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new,
-				uint32_t len, struct jffs2_inode_cache *ic)
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
+						       uint32_t ofs, uint32_t len,
+						       struct jffs2_inode_cache *ic)
 {
 	struct jffs2_eraseblock *jeb;
+	struct jffs2_raw_node_ref *new;
 
-	jeb = &c->blocks[new->flash_offset / c->sector_size];
-#ifdef TEST_TOTLEN
-	new->__totlen = len;
-#endif
+	jeb = &c->blocks[ofs / c->sector_size];
 
-	D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));
+	D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
+		  ofs & ~3, ofs & 3, len));
 #if 1
-	/* we could get some obsolete nodes after nextblock was refiled
-	   in wbuf.c */
-	if ((c->nextblock || !ref_obsolete(new))
-	    &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {
+	/* Allow non-obsolete nodes only to be added at the end of c->nextblock, 
+	   if c->nextblock is set. Note that wbuf.c will file obsolete nodes
+	   even after refiling c->nextblock */
+	if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
+	    && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
 		printk(KERN_WARNING "argh. node added in wrong place\n");
-		jffs2_free_raw_node_ref(new);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 #endif
 	spin_lock(&c->erase_completion_lock);
 
-	jffs2_link_node_ref(c, jeb, new, len, ic);
+	new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
 
 	if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
 		/* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -425,7 +430,7 @@
 
 	spin_unlock(&c->erase_completion_lock);
 
-	return 0;
+	return new;
 }
 
 
@@ -697,7 +702,7 @@
 		}
 		spin_unlock(&c->erase_completion_lock);
 
-		jffs2_free_raw_node_ref(n);
+		__jffs2_free_raw_node_ref(n);
 	}
 
 	/* Also merge with the previous node in the list, if there is one
@@ -722,7 +727,7 @@
 				jeb->gc_node=p;
 			}
 			p->next_phys = ref->next_phys;
-			jffs2_free_raw_node_ref(ref);
+			__jffs2_free_raw_node_ref(ref);
 		}
 		spin_unlock(&c->erase_completion_lock);
 	}
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 6fce703..87b0a41 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -317,7 +317,6 @@
 				 struct jffs2_summary *s)
 {
 	struct jffs2_xattr_datum *xd;
-	struct jffs2_raw_node_ref *raw;
 	uint32_t totlen, crc;
 	int err;
 
@@ -340,13 +339,8 @@
 		return 0;
 	}
 
-	raw =  jffs2_alloc_raw_node_ref();
-	if (!raw)
-		return -ENOMEM;
-
 	xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version));
 	if (IS_ERR(xd)) {
-		jffs2_free_raw_node_ref(raw);
 		if (PTR_ERR(xd) == -EEXIST) {
 			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
 				return err;
@@ -358,12 +352,9 @@
 	xd->name_len = rx->name_len;
 	xd->value_len = je16_to_cpu(rx->value_len);
 	xd->data_crc = je32_to_cpu(rx->data_crc);
-	xd->node = raw;
 
-	raw->flash_offset = ofs | REF_PRISTINE;
-
-	jffs2_link_node_ref(c, jeb, raw, totlen, NULL);
-	/* FIXME */ raw->next_in_ino = (void *)xd;
+	xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
+	/* FIXME */ xd->node->next_in_ino = (void *)xd;
 
 	if (jffs2_sum_active())
 		jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
@@ -377,7 +368,6 @@
 				struct jffs2_summary *s)
 {
 	struct jffs2_xattr_ref *ref;
-	struct jffs2_raw_node_ref *raw;
 	uint32_t crc;
 	int err;
 
@@ -404,12 +394,6 @@
 	if (!ref)
 		return -ENOMEM;
 
-	raw =  jffs2_alloc_raw_node_ref();
-	if (!raw) {
-		jffs2_free_xattr_ref(ref);
-		return -ENOMEM;
-	}
-
 	/* BEFORE jffs2_build_xattr_subsystem() called, 
 	 * ref->xid is used to store 32bit xid, xd is not used
 	 * ref->ino is used to store 32bit inode-number, ic is not used
@@ -418,16 +402,13 @@
 	 * used to chain all xattr_ref object. It's re-chained to
 	 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
 	 */
-	ref->node = raw;
 	ref->ino = je32_to_cpu(rr->ino);
 	ref->xid = je32_to_cpu(rr->xid);
 	ref->next = c->xref_temp;
 	c->xref_temp = ref;
 
-	raw->flash_offset = ofs | REF_PRISTINE;
-
-	jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)), NULL);
-	/* FIXME */ raw->next_in_ino = (void *)ref;
+	ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL);
+	/* FIXME */ ref->node->next_in_ino = (void *)ref;
 
 	if (jffs2_sum_active())
 		jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
@@ -597,6 +578,11 @@
 
 		jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 
+		/* Make sure there are node refs available for use */
+		err = jffs2_prealloc_raw_node_refs(c, 2);
+		if (err)
+			return err;
+
 		cond_resched();
 
 		if (ofs & 3) {
@@ -839,14 +825,7 @@
 					return err;
 				ofs += PAD(sizeof(struct jffs2_unknown_node));
 			} else {
-				struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
-				if (!marker_ref) {
-					printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");
-					return -ENOMEM;
-				}
-				marker_ref->flash_offset = ofs | REF_NORMAL;
-
-				jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
+				jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
 
 				ofs += PAD(c->cleanmarker_size);
 			}
@@ -884,14 +863,9 @@
 				break;
 
 			case JFFS2_FEATURE_RWCOMPAT_COPY: {
-				struct jffs2_raw_node_ref *ref;
 				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
 
-				ref = jffs2_alloc_raw_node_ref();
-				if (!ref)
-					return -ENOMEM;
-				ref->flash_offset = ofs | REF_PRISTINE;
-				jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)), NULL);
+				jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
 
 				/* We can't summarise nodes we don't grok */
 				jffs2_sum_disable_collecting(s);
@@ -953,7 +927,6 @@
 static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_inode_cache *ic;
 	uint32_t ino = je32_to_cpu(ri->ino);
 	int err;
@@ -969,12 +942,6 @@
 	   Which means that the _full_ amount of time to get to proper write mode with GC
 	   operational may actually be _longer_ than before. Sucks to be me. */
 
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw) {
-		printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
-		return -ENOMEM;
-	}
-
 	ic = jffs2_get_ino_cache(c, ino);
 	if (!ic) {
 		/* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
@@ -988,21 +955,15 @@
 			/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
 			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
 				return err;
-			jffs2_free_raw_node_ref(raw);
 			return 0;
 		}
 		ic = jffs2_scan_make_ino_cache(c, ino);
-		if (!ic) {
-			jffs2_free_raw_node_ref(raw);
+		if (!ic)
 			return -ENOMEM;
-		}
 	}
 
 	/* Wheee. It worked */
-
-	raw->flash_offset = ofs | REF_UNCHECKED;
-
-	jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)), ic);
+	jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
 
 	D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
 		  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
@@ -1021,7 +982,6 @@
 static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				  struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dirent *fd;
 	struct jffs2_inode_cache *ic;
 	uint32_t crc;
@@ -1063,23 +1023,14 @@
 			return err;
 		return 0;
 	}
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw) {
-		jffs2_free_full_dirent(fd);
-		printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");
-		return -ENOMEM;
-	}
 	ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
 	if (!ic) {
 		jffs2_free_full_dirent(fd);
-		jffs2_free_raw_node_ref(raw);
 		return -ENOMEM;
 	}
 
-	raw->flash_offset = ofs | REF_PRISTINE;
-	jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)), ic);
+	fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
 
-	fd->raw = raw;
 	fd->next = NULL;
 	fd->version = je32_to_cpu(rd->version);
 	fd->ino = je32_to_cpu(rd->ino);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 351ba9f..ccb6803 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -369,22 +369,18 @@
 	return -ENOMEM;
 }
 
-static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-					       uint32_t offset)
+static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
+						    struct jffs2_eraseblock *jeb,
+						    uint32_t ofs, uint32_t len,
+						    struct jffs2_inode_cache *ic)
 {
-	struct jffs2_raw_node_ref *ref;
 	/* If there was a gap, mark it dirty */
-	if (offset > c->sector_size - jeb->free_size) {
-		int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size));
-		if (ret)
-			return NULL;
+	if ((ofs & ~3) > c->sector_size - jeb->free_size) {
+		/* Ew. Summary doesn't actually tell us explicitly about dirty space */
+		jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
 	}
-	ref = jffs2_alloc_raw_node_ref();
-	if (!ref)
-		return NULL;
 
-	ref->flash_offset = jeb->offset + offset;
-	return ref;
+	return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
 }
 
 /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
@@ -392,7 +388,6 @@
 static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_inode_cache *ic;
 	struct jffs2_full_dirent *fd;
 	void *sp;
@@ -404,6 +399,11 @@
 	for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
 		dbg_summary("processing summary index %d\n", i);
 
+		/* Make sure there's a spare ref for dirty space */
+		err = jffs2_prealloc_raw_node_refs(c, 2);
+		if (err)
+			return err;
+
 		switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
 			case JFFS2_NODETYPE_INODE: {
 				struct jffs2_sum_inode_flash *spi;
@@ -415,22 +415,14 @@
 					    jeb->offset + je32_to_cpu(spi->offset),
 					    jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen));
 
-				raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset));
-				if (!raw) {
-					JFFS2_NOTICE("allocation of node reference failed\n");
-					return -ENOMEM;
-				}
-
 				ic = jffs2_scan_make_ino_cache(c, ino);
 				if (!ic) {
 					JFFS2_NOTICE("scan_make_ino_cache failed\n");
-					jffs2_free_raw_node_ref(raw);
 					return -ENOMEM;
 				}
 
-				raw->flash_offset |= REF_UNCHECKED;
-
-				jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)), ic);
+				sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
+						  PAD(je32_to_cpu(spi->totlen)), ic);
 
 				*pseudo_random += je32_to_cpu(spi->version);
 
@@ -455,24 +447,15 @@
 				memcpy(&fd->name, spd->name, spd->nsize);
 				fd->name[spd->nsize] = 0;
 
-				raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset));
-				if (!raw) {
-					jffs2_free_full_dirent(fd);
-					JFFS2_NOTICE("allocation of node reference failed\n");
-					return -ENOMEM;
-				}
-
 				ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
 				if (!ic) {
 					jffs2_free_full_dirent(fd);
-					jffs2_free_raw_node_ref(raw);
 					return -ENOMEM;
 				}
 
-				raw->flash_offset |= REF_PRISTINE;
-				jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)), ic);
+				fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_PRISTINE,
+							    PAD(je32_to_cpu(spd->totlen)), ic);
 
-				fd->raw = raw;
 				fd->next = NULL;
 				fd->version = je32_to_cpu(spd->version);
 				fd->ino = je32_to_cpu(spd->ino);
@@ -497,15 +480,10 @@
 					    jeb->offset + je32_to_cpu(spx->offset),
 					    jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
 					    je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
-				raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset));
-				if (!raw) {
-					JFFS2_NOTICE("allocation of node reference failed\n");
-					return -ENOMEM;
-				}
+
 				xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
 								je32_to_cpu(spx->version));
 				if (IS_ERR(xd)) {
-					jffs2_free_raw_node_ref(raw);
 					if (PTR_ERR(xd) == -EEXIST) {
 						/* a newer version of xd exists */
 						if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
@@ -516,12 +494,10 @@
 					JFFS2_NOTICE("allocation of xattr_datum failed\n");
 					return PTR_ERR(xd);
 				}
-				xd->node = raw;
 
-				raw->flash_offset |= REF_UNCHECKED;
-
-				jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)), NULL);
-				/* FIXME */ raw->next_in_ino = (void *)xd;
+				xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
+							     PAD(je32_to_cpu(spx->totlen)), NULL);
+				/* FIXME */ xd->node->next_in_ino = (void *)xd;
 
 				*pseudo_random += je32_to_cpu(spx->xid);
 				sp += JFFS2_SUMMARY_XATTR_SIZE;
@@ -537,29 +513,21 @@
 					    jeb->offset + je32_to_cpu(spr->offset),
 					    jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref)));
 
-				raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset));
-				if (!raw) {
-					JFFS2_NOTICE("allocation of node reference failed\n");
-					return -ENOMEM;
-				}
 				ref = jffs2_alloc_xattr_ref();
 				if (!ref) {
 					JFFS2_NOTICE("allocation of xattr_datum failed\n");
-					jffs2_free_raw_node_ref(raw);
 					return -ENOMEM;
 				}
 				ref->ino = 0xfffffffe;
 				ref->xid = 0xfffffffd;
-				ref->node = raw;
 				ref->next = c->xref_temp;
 				c->xref_temp = ref;
 
-				raw->flash_offset |= REF_UNCHECKED;
+				ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
+							      PAD(sizeof(struct jffs2_raw_xref)), NULL);
+				/* FIXME */ ref->node->next_in_ino = (void *)ref;
 
-				jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)), NULL);
-				/* FIXME */ raw->next_in_ino = (void *)ref;
-
-				*pseudo_random += raw->flash_offset;
+				*pseudo_random += ref->node->flash_offset;
 				sp += JFFS2_SUMMARY_XREF_SIZE;
 
 				break;
@@ -584,7 +552,6 @@
 			}
 		}
 	}
-
 	return 0;
 }
 
@@ -594,7 +561,6 @@
 			   uint32_t *pseudo_random)
 {
 	struct jffs2_unknown_node crcnode;
-	struct jffs2_raw_node_ref *cache_ref;
 	int ret, ofs;
 	uint32_t crc;
 	int err;
@@ -650,16 +616,8 @@
 			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
 				return err;
 		} else {
-			struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
-
-			if (!marker_ref) {
-				JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
-				return -ENOMEM;
-			}
-
-			marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-
-			jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr), NULL);
+			jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
+					    je32_to_cpu(summary->cln_mkr), NULL);
 		}
 	}
 
@@ -672,16 +630,11 @@
 		return ret;		/* real error */
 
 	/* for PARANOIA_CHECK */
-	cache_ref = alloc_ref_at(c, jeb, ofs);
+	ret = jffs2_prealloc_raw_node_refs(c, 1);
+	if (ret)
+		return ret;
 
-	if (!cache_ref) {
-		JFFS2_NOTICE("Failed to allocate node ref for cache\n");
-		return -ENOMEM;
-	}
-
-	cache_ref->flash_offset |= REF_NORMAL;
-
-	jffs2_link_node_ref(c, jeb, cache_ref, sumsize, NULL);
+	jffs2_link_node_ref(c, jeb, (jeb->offset + ofs) | REF_NORMAL, sumsize, NULL);
 
 	if (unlikely(jeb->free_size)) {
 		JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
@@ -709,6 +662,7 @@
 	union jffs2_sum_mem *temp;
 	struct jffs2_sum_marker *sm;
 	struct kvec vecs[2];
+	uint32_t sum_ofs;
 	void *wpage;
 	int ret;
 	size_t retlen;
@@ -821,36 +775,31 @@
 	vecs[1].iov_base = c->summary->sum_buf;
 	vecs[1].iov_len = datasize;
 
-	dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
-			jeb->offset + c->sector_size - jeb->free_size);
+	sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
 
-	spin_unlock(&c->erase_completion_lock);
-	ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
-				jeb->free_size, &retlen, 0);
+	dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
+		    sum_ofs);
+
+	ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
 
 	if (ret || (retlen != infosize)) {
-		struct jffs2_raw_node_ref *ref;
 
 		JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
-			infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
+			      infosize, sum_ofs, ret, retlen);
 
 		/* Waste remaining space */
-		ref = jffs2_alloc_raw_node_ref();
-		if (ref) {
-			spin_lock(&c->erase_completion_lock);
-
-			ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
-			ref->flash_offset |= REF_OBSOLETE;
-
-			jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size, NULL);
-		}
+		spin_lock(&c->erase_completion_lock);
+		jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
+		spin_unlock(&c->erase_completion_lock);
 
 		c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
 
-		return 1;
+		return 0;
 	}
 
 	spin_lock(&c->erase_completion_lock);
+	jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
+	spin_unlock(&c->erase_completion_lock);
 
 	return 0;
 }
@@ -859,12 +808,15 @@
 
 int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
 {
-	struct jffs2_raw_node_ref *summary_ref;
-	int datasize, infosize, padsize, ret;
+	int datasize, infosize, padsize;
 	struct jffs2_eraseblock *jeb;
+	int ret;
 
 	dbg_summary("called\n");
 
+	spin_unlock(&c->erase_completion_lock);
+	jffs2_prealloc_raw_node_refs(c, 1);
+
 	jeb = c->nextblock;
 
 	if (!c->summary->sum_num || !c->summary->sum_list_head) {
@@ -888,22 +840,6 @@
 	}
 
 	ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
-	if (ret)
-		return 0; /* can't write out summary, block is marked as NOSUM_SIZE */
-
-	/* for ACCT_PARANOIA_CHECK */
-	spin_unlock(&c->erase_completion_lock);
-	summary_ref = jffs2_alloc_raw_node_ref();
-
-	if (!summary_ref) {
-		JFFS2_NOTICE("Failed to allocate node ref for summary\n");
-		return -ENOMEM;
-	}
-
-	summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
-
 	spin_lock(&c->erase_completion_lock);
-	jffs2_link_node_ref(c, jeb, summary_ref, infosize, NULL);
-
-	return 0;
+	return ret;
 }
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 916c87d..0d7abb2 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -179,6 +179,9 @@
 	unsigned char *buf;
 	uint32_t start, end, ofs, len;
 
+	if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
+		return;
+
 	spin_lock(&c->erase_completion_lock);
 
 	jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
@@ -306,17 +309,9 @@
 			printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
 			kfree(buf);
 
-			if (retlen) {
-				struct jffs2_raw_node_ref *raw2;
+			if (retlen)
+				jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL);
 
-				raw2 = jffs2_alloc_raw_node_ref();
-				if (!raw2)
-					return;
-
-				raw2->flash_offset = ofs | REF_OBSOLETE;
-
-				jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw), NULL);
-			}
 			return;
 		}
 		printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs);
@@ -428,6 +423,9 @@
 	if (!c->wbuf_len)	/* already checked c->wbuf above */
 		return 0;
 
+	if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
+		return -ENOMEM;
+
 	/* claim remaining space on the page
 	   this happens, if we have a change to a new block,
 	   or if fsync forces us to flush the writebuffer.
@@ -485,7 +483,6 @@
 	/* Adjust free size of the block if we padded. */
 	if (pad) {
 		struct jffs2_eraseblock *jeb;
-		struct jffs2_raw_node_ref *ref;
 		uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
 
 		jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
@@ -503,15 +500,10 @@
 			       jeb->offset, jeb->free_size);
 			BUG();
 		}
-		ref = jffs2_alloc_raw_node_ref();
-		if (!ref)
-			return -ENOMEM;
-		ref->flash_offset = c->wbuf_ofs + c->wbuf_len;
-		ref->flash_offset |= REF_OBSOLETE;
 
 		spin_lock(&c->erase_completion_lock);
 
-		jffs2_link_node_ref(c, jeb, ref, waste, NULL);
+		jffs2_link_node_ref(c, jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL);
 		/* FIXME: that made it count as dirty. Convert to wasted */
 		jeb->dirty_size -= waste;
 		c->dirty_size -= waste;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 0e12b75..6717679 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -61,7 +61,6 @@
 					   uint32_t datalen, int alloc_mode)
 
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dnode *fn;
 	size_t retlen;
 	uint32_t flash_ofs;
@@ -83,27 +82,16 @@
 	if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
 		printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
 	}
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw)
-		return ERR_PTR(-ENOMEM);
 
 	fn = jffs2_alloc_full_dnode();
-	if (!fn) {
-		jffs2_free_raw_node_ref(raw);
+	if (!fn)
 		return ERR_PTR(-ENOMEM);
-	}
-
-	fn->ofs = je32_to_cpu(ri->offset);
-	fn->size = je32_to_cpu(ri->dsize);
-	fn->frags = 0;
 
 	/* check number of valid vecs */
 	if (!datalen || !data)
 		cnt = 1;
  retry:
-	fn->raw = raw;
-
-	raw->flash_offset = flash_ofs = write_ofs(c);
+	flash_ofs = write_ofs(c);
 
 	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
 
@@ -130,14 +118,11 @@
 			   seem corrupted, in which case the scan would skip over
 			   any node we write before the original intended end of
 			   this node */
-			raw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL);
-			jffs2_mark_node_obsolete(c, raw);
+			jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
 		} else {
-			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
-			jffs2_free_raw_node_ref(raw);
+			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
 		}
-		if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) {
+		if (!retried && alloc_mode != ALLOC_NORETRY) {
 			/* Try to reallocate space and retry */
 			uint32_t dummy;
 			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -172,7 +157,6 @@
 				goto retry;
 			}
 			D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-			jffs2_free_raw_node_ref(raw);
 		}
 		/* Release the full_dnode which is now useless, and return */
 		jffs2_free_full_dnode(fn);
@@ -186,14 +170,17 @@
 	if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
 	    ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
 	      (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) ==  je32_to_cpu(ri->isize)))) {
-		raw->flash_offset |= REF_PRISTINE;
+		flash_ofs |= REF_PRISTINE;
 	} else {
-		raw->flash_offset |= REF_NORMAL;
+		flash_ofs |= REF_NORMAL;
 	}
-	jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache);
+	fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
+	fn->ofs = je32_to_cpu(ri->offset);
+	fn->size = je32_to_cpu(ri->dsize);
+	fn->frags = 0;
 
 	D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
-		  flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
+		  flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
 		  je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
 		  je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
 
@@ -208,11 +195,10 @@
 					     struct jffs2_raw_dirent *rd, const unsigned char *name,
 					     uint32_t namelen, int alloc_mode)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dirent *fd;
 	size_t retlen;
 	struct kvec vecs[2];
-	uint32_t flash_ofs = write_ofs(c);
+	uint32_t flash_ofs;
 	int retried = 0;
 	int ret;
 
@@ -223,26 +209,16 @@
 	D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
 		printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
 		BUG();
-	}
-	   );
+	   });
 
 	vecs[0].iov_base = rd;
 	vecs[0].iov_len = sizeof(*rd);
 	vecs[1].iov_base = (unsigned char *)name;
 	vecs[1].iov_len = namelen;
 
-	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
-
-	raw = jffs2_alloc_raw_node_ref();
-
-	if (!raw)
-		return ERR_PTR(-ENOMEM);
-
 	fd = jffs2_alloc_full_dirent(namelen+1);
-	if (!fd) {
-		jffs2_free_raw_node_ref(raw);
+	if (!fd)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	fd->version = je32_to_cpu(rd->version);
 	fd->ino = je32_to_cpu(rd->ino);
@@ -252,9 +228,9 @@
 	fd->name[namelen]=0;
 
  retry:
-	fd->raw = raw;
+	flash_ofs = write_ofs(c);
 
-	raw->flash_offset = flash_ofs;
+	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
 
 	if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
 		BUG_ON(!retried);
@@ -273,14 +249,11 @@
 			       sizeof(*rd)+namelen, flash_ofs, ret, retlen);
 		/* Mark the space as dirtied */
 		if (retlen) {
-			raw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL);
-			jffs2_mark_node_obsolete(c, raw);
+			jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
 		} else {
-			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
-			jffs2_free_raw_node_ref(raw);
+			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
 		}
-		if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
+		if (!retried) {
 			/* Try to reallocate space and retry */
 			uint32_t dummy;
 			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -313,15 +286,13 @@
 				goto retry;
 			}
 			D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-			jffs2_free_raw_node_ref(raw);
 		}
 		/* Release the full_dnode which is now useless, and return */
 		jffs2_free_full_dirent(fd);
 		return ERR_PTR(ret?ret:-EIO);
 	}
 	/* Mark the space used */
-	raw->flash_offset |= REF_PRISTINE;
-	jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache);
+	fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache);
 
 	if (retried) {
 		jffs2_dbg_acct_sanity_check(c,NULL);
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 008f91b..2255f13 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -304,8 +304,8 @@
 static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
 {
 	/* must be called under down_write(xattr_sem) */
-	struct jffs2_raw_xattr rx;
 	struct jffs2_raw_node_ref *raw;
+	struct jffs2_raw_xattr rx;
 	struct kvec vecs[2];
 	uint32_t length;
 	int rc, totlen;
@@ -319,11 +319,6 @@
 	vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
 	totlen = vecs[0].iov_len + vecs[1].iov_len;
 
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw)
-		return -ENOMEM;
-	raw->flash_offset = phys_ofs;
-
 	/* Setup raw-xattr */
 	rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
 	rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
@@ -343,19 +338,14 @@
 		JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n",
 			      rc, totlen, length, phys_ofs);
 		rc = rc ? rc : -EIO;
-		if (length) {
-			raw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL);
-			jffs2_mark_node_obsolete(c, raw);
-		} else {
-			jffs2_free_raw_node_ref(raw);
-		}
+		if (length)
+			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
+
 		return rc;
 	}
 
 	/* success */
-	raw->flash_offset |= REF_PRISTINE;
-	jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL);
+	raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL);
 	/* FIXME */ raw->next_in_ino = (void *)xd;
 
 	if (xd->node)
@@ -563,11 +553,6 @@
 	uint32_t phys_ofs = write_ofs(c);
 	int ret;
 
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw)
-		return -ENOMEM;
-	raw->flash_offset = phys_ofs;
-
 	rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
 	rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
 	rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
@@ -582,18 +567,13 @@
 		JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n",
 			      ret, sizeof(rr), length, phys_ofs);
 		ret = ret ? ret : -EIO;
-		if (length) {
-			raw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL);
-			jffs2_mark_node_obsolete(c, raw);
-		} else {
-			jffs2_free_raw_node_ref(raw);
-		}
+		if (length)
+			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
+
 		return ret;
 	}
-	raw->flash_offset |= REF_PRISTINE;
 
-	jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL);
+	raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL);
 	/* FIXME */ raw->next_in_ino = (void *)ref;
 	if (ref->node)
 		delete_xattr_ref_node(c, ref);