[JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code.
David Woodhouse [Wed, 24 May 2006 01:04:45 +0000 (02:04 +0100)]
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>

12 files changed:
fs/jffs2/erase.c
fs/jffs2/gc.c
fs/jffs2/jffs2_fs_sb.h
fs/jffs2/malloc.c
fs/jffs2/nodelist.c
fs/jffs2/nodelist.h
fs/jffs2/nodemgmt.c
fs/jffs2/scan.c
fs/jffs2/summary.c
fs/jffs2/wbuf.c
fs/jffs2/write.c
fs/jffs2/xattr.c

index 4616fed..f939f90 100644 (file)
@@ -296,7 +296,7 @@ void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *
                        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 @@ fail:
 
 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 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
                        .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 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
                                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);
index f9e982a..a22ff5d 100644 (file)
@@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                                          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 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                }
        }
 
-       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 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                                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)));
index 272fbea..67529f0 100644 (file)
@@ -26,6 +26,9 @@ struct jffs2_inodirty;
 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;
 
index f2473fa..3df3250 100644 (file)
@@ -190,7 +190,29 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
        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 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
        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);
index d25d491..1e6eabd 100644 (file)
@@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
 
        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_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
        }
 }
 
-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 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
        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 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
                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;
-
-               ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
-               ref->flash_offset |= REF_OBSOLETE;
-#ifdef TEST_TOTLEN
-               ref->__totlen = size;
-#endif
+               uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
+               ofs |= REF_OBSOLETE;
 
-               jffs2_link_node_ref(c, jeb, ref, size, NULL);
+               jffs2_link_node_ref(c, jeb, ofs, size, NULL);
        }
 
        return 0;
index 76f1b94..7cc74d2 100644 (file)
@@ -318,9 +318,10 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
 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 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        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 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
 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);
index 8feb874..01bf277 100644 (file)
@@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                }
        }
        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 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
                }
        }
        spin_unlock(&c->erase_completion_lock);
+       if (!ret)
+               ret = jffs2_prealloc_raw_node_refs(c, 1);
+
        return ret;
 }
 
@@ -381,30 +386,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
  *     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 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
 
        spin_unlock(&c->erase_completion_lock);
 
-       return 0;
+       return new;
 }
 
 
@@ -697,7 +702,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                }
                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 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                                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);
        }
index 6fce703..87b0a41 100644 (file)
@@ -317,7 +317,6 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
                                 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 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
                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 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
        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 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
                                struct jffs2_summary *s)
 {
        struct jffs2_xattr_ref *ref;
-       struct jffs2_raw_node_ref *raw;
        uint32_t crc;
        int err;
 
@@ -404,12 +394,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
        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 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
         * 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 @@ scan_more:
 
                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 @@ scan_more:
                                        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 @@ scan_more:
                                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 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
 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 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
           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 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
                        /* 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_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
 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 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
                        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);
index 351ba9f..ccb6803 100644 (file)
@@ -369,22 +369,18 @@ no_mem:
        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 struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct j
 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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
        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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                            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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                            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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                        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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                            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 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                        }
                }
        }
-
        return 0;
 }
 
@@ -594,7 +561,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
                           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 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
                        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 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
                return ret;             /* real error */
 
        /* for PARANOIA_CHECK */
-       cache_ref = alloc_ref_at(c, jeb, ofs);
-
-       if (!cache_ref) {
-               JFFS2_NOTICE("Failed to allocate node ref for cache\n");
-               return -ENOMEM;
-       }
-
-       cache_ref->flash_offset |= REF_NORMAL;
+       ret = jffs2_prealloc_raw_node_refs(c, 1);
+       if (ret)
+               return ret;
 
-       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 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
        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 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
        vecs[1].iov_base = c->summary->sum_buf;
        vecs[1].iov_len = datasize;
 
+       sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
+
        dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
-                       jeb->offset + c->sector_size - jeb->free_size);
+                   sum_ofs);
 
-       spin_unlock(&c->erase_completion_lock);
-       ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
-                               jeb->free_size, &retlen, 0);
+       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 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
 
 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 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
        }
 
        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;
 }
index 916c87d..0d7abb2 100644 (file)
@@ -179,6 +179,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
        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 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
                        printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
                        kfree(buf);
 
-                       if (retlen) {
-                               struct jffs2_raw_node_ref *raw2;
-
-                               raw2 = jffs2_alloc_raw_node_ref();
-                               if (!raw2)
-                                       return;
-
-                               raw2->flash_offset = ofs | REF_OBSOLETE;
+                       if (retlen)
+                               jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL);
 
-                               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 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        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 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        /* 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 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
                               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;
index 0e12b75..6717679 100644 (file)
@@ -61,7 +61,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
                                           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 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
        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 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
                           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 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
                                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 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
        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_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
                                             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 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
        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 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
        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 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
                               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 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
                                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);
index 008f91b..2255f13 100644 (file)
@@ -304,8 +304,8 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
 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 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
        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 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
                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 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
        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 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
                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);