nfsd4: cl_count is unused
[safe/jmp/linux-2.6] / fs / jffs2 / scan.c
index 805a166..696686c 100644 (file)
@@ -1,15 +1,14 @@
 /*
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $
- *
  */
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -38,11 +37,11 @@ static uint32_t pseudo_random;
 static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
                                  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s);
 
-/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. 
+/* These helper functions _must_ increase ofs and also do the dirty/used space accounting.
  * Returning an error will abort the mount - bad checksums etc. should just mark the space
  * as dirty.
  */
-static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 
+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);
 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);
@@ -65,6 +64,28 @@ static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {
                return DEFAULT_EMPTY_SCAN_SIZE;
 }
 
+static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+{
+       int ret;
+
+       if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
+               return ret;
+       if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
+               return ret;
+       /* Turned wasted size into dirty, since we apparently 
+          think it's recoverable now. */
+       jeb->dirty_size += jeb->wasted_size;
+       c->dirty_size += jeb->wasted_size;
+       c->wasted_size -= jeb->wasted_size;
+       jeb->wasted_size = 0;
+       if (VERYDIRTY(c, jeb->dirty_size)) {
+               list_add(&jeb->list, &c->very_dirty_list);
+       } else {
+               list_add(&jeb->list, &c->dirty_list);
+       }
+       return 0;
+}
+
 int jffs2_scan_medium(struct jffs2_sb_info *c)
 {
        int i, ret;
@@ -76,11 +97,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        size_t pointlen;
 
        if (c->mtd->point) {
-               ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf);
+               ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen,
+                                   (void **)&flashbuf, NULL);
                if (!ret && pointlen < c->mtd->size) {
                        /* Don't muck about if it won't let us point to the whole flash */
                        D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
-                       c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
+                       c->mtd->unpoint(c->mtd, 0, pointlen);
                        flashbuf = NULL;
                }
                if (ret)
@@ -106,17 +128,19 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        }
 
        if (jffs2_sum_active()) {
-               s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
+               s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
                if (!s) {
                        JFFS2_WARNING("Can't allocate memory for summary\n");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto out;
                }
-               memset(s, 0, sizeof(struct jffs2_summary));
        }
 
        for (i=0; i<c->nr_blocks; i++) {
                struct jffs2_eraseblock *jeb = &c->blocks[i];
 
+               cond_resched();
+
                /* reset summary info for next eraseblock scan */
                jffs2_sum_reset_collected(s);
 
@@ -131,8 +155,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                /* Now decide which list to put it on */
                switch(ret) {
                case BLK_STATE_ALLFF:
-                       /* 
-                        * Empty block.   Since we can't be sure it 
+                       /*
+                        * Empty block.   Since we can't be sure it
                         * was entirely erased, we just queue it for erase
                         * again.  It will be marked as such when the erase
                         * is complete.  Meanwhile we still count it as empty
@@ -170,34 +194,20 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                                        (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
                                /* Better candidate for the next writes to go to */
                                if (c->nextblock) {
-                                       c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
-                                       c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
-                                       c->free_size -= c->nextblock->free_size;
-                                       c->wasted_size -= c->nextblock->wasted_size;
-                                       c->nextblock->free_size = c->nextblock->wasted_size = 0;
-                                       if (VERYDIRTY(c, c->nextblock->dirty_size)) {
-                                               list_add(&c->nextblock->list, &c->very_dirty_list);
-                                       } else {
-                                               list_add(&c->nextblock->list, &c->dirty_list);
-                                       }
+                                       ret = file_dirty(c, c->nextblock);
+                                       if (ret)
+                                               goto out;
                                        /* deleting summary information of the old nextblock */
                                        jffs2_sum_reset_collected(c->summary);
                                }
-                               /* update collected summary infromation for the current nextblock */
+                               /* update collected summary information for the current nextblock */
                                jffs2_sum_move_collected(c, s);
                                D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset));
                                c->nextblock = jeb;
                        } else {
-                               jeb->dirty_size += jeb->free_size + jeb->wasted_size;
-                               c->dirty_size += jeb->free_size + jeb->wasted_size;
-                               c->free_size -= jeb->free_size;
-                               c->wasted_size -= jeb->wasted_size;
-                               jeb->free_size = jeb->wasted_size = 0;
-                               if (VERYDIRTY(c, jeb->dirty_size)) {
-                                       list_add(&jeb->list, &c->very_dirty_list);
-                               } else {
-                                       list_add(&jeb->list, &c->dirty_list);
-                               }
+                               ret = file_dirty(c, jeb);
+                               if (ret)
+                                       goto out;
                        }
                        break;
 
@@ -222,9 +232,6 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                }
        }
 
-       if (jffs2_sum_active() && s)
-               kfree(s);
-
        /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
        if (c->nextblock && (c->nextblock->dirty_size)) {
                c->nextblock->wasted_size += c->nextblock->dirty_size;
@@ -233,8 +240,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                c->nextblock->dirty_size = 0;
        }
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-       if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
-               /* If we're going to start writing into a block which already 
+       if (!jffs2_can_mark_obsolete(c) && c->wbuf_pagesize && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
+               /* If we're going to start writing into a block which already
                   contains data, and the end of the data isn't page-aligned,
                   skip a little and align it. */
 
@@ -242,15 +249,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
 
                D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
                          skip));
-               c->nextblock->wasted_size += skip;
-               c->wasted_size += skip;
-
-               c->nextblock->free_size -= skip;
-               c->free_size -= skip;
+               jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+               jffs2_scan_dirty_space(c, c->nextblock, skip);
        }
 #endif
        if (c->nr_erasing_blocks) {
-               if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { 
+               if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
                        printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
                        printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks);
                        ret = -EIO;
@@ -263,14 +267,17 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        if (buf_size)
                kfree(flashbuf);
 #ifndef __ECOS
-       else 
-               c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
+       else
+               c->mtd->unpoint(c->mtd, 0, c->mtd->size);
 #endif
+       if (s)
+               kfree(s);
+
        return ret;
 }
 
-int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf,
-                               uint32_t ofs, uint32_t len)
+static int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
+                              uint32_t ofs, uint32_t len)
 {
        int ret;
        size_t retlen;
@@ -284,16 +291,13 @@ int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf,
                D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes\n", ofs, retlen));
                return -EIO;
        }
-       D2(printk(KERN_DEBUG "Read 0x%x bytes from 0x%08x into buf\n", len, ofs));
-       D2(printk(KERN_DEBUG "000: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-                 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]));
        return 0;
 }
 
 int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
        if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
-               && (!jeb->first_node || !jeb->first_node->next_phys) )
+           && (!jeb->first_node || !ref_next(jeb->first_node)) )
                return BLK_STATE_CLEANMARKER;
 
        /* move blocks with max 4 byte dirty space to cleanlist */
@@ -309,11 +313,126 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
                return BLK_STATE_ALLDIRTY;
 }
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                                struct jffs2_raw_xattr *rx, uint32_t ofs,
+                                struct jffs2_summary *s)
+{
+       struct jffs2_xattr_datum *xd;
+       uint32_t xid, version, totlen, crc;
+       int err;
+
+       crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
+       if (crc != je32_to_cpu(rx->node_crc)) {
+               JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                             ofs, je32_to_cpu(rx->node_crc), crc);
+               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
+                       return err;
+               return 0;
+       }
+
+       xid = je32_to_cpu(rx->xid);
+       version = je32_to_cpu(rx->version);
+
+       totlen = PAD(sizeof(struct jffs2_raw_xattr)
+                       + rx->name_len + 1 + je16_to_cpu(rx->value_len));
+       if (totlen != je32_to_cpu(rx->totlen)) {
+               JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
+                             ofs, je32_to_cpu(rx->totlen), totlen);
+               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
+                       return err;
+               return 0;
+       }
+
+       xd = jffs2_setup_xattr_datum(c, xid, version);
+       if (IS_ERR(xd))
+               return PTR_ERR(xd);
+
+       if (xd->version > version) {
+               struct jffs2_raw_node_ref *raw
+                       = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
+               raw->next_in_ino = xd->node->next_in_ino;
+               xd->node->next_in_ino = raw;
+       } else {
+               xd->version = version;
+               xd->xprefix = rx->xprefix;
+               xd->name_len = rx->name_len;
+               xd->value_len = je16_to_cpu(rx->value_len);
+               xd->data_crc = je32_to_cpu(rx->data_crc);
+
+               jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
+       }
+
+       if (jffs2_sum_active())
+               jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
+       dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
+                 ofs, xd->xid, xd->version);
+       return 0;
+}
+
+static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                               struct jffs2_raw_xref *rr, uint32_t ofs,
+                               struct jffs2_summary *s)
+{
+       struct jffs2_xattr_ref *ref;
+       uint32_t crc;
+       int err;
+
+       crc = crc32(0, rr, sizeof(*rr) - 4);
+       if (crc != je32_to_cpu(rr->node_crc)) {
+               JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                             ofs, je32_to_cpu(rr->node_crc), crc);
+               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
+                       return err;
+               return 0;
+       }
+
+       if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
+               JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n",
+                             ofs, je32_to_cpu(rr->totlen),
+                             PAD(sizeof(struct jffs2_raw_xref)));
+               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
+                       return err;
+               return 0;
+       }
+
+       ref = jffs2_alloc_xattr_ref();
+       if (!ref)
+               return -ENOMEM;
+
+       /* BEFORE jffs2_build_xattr_subsystem() called, 
+        * and AFTER xattr_ref is marked as a dead xref,
+        * 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
+        * Thoes variables are declared as union, thus using those
+        * are exclusive. In a similar way, ref->next is temporarily
+        * used to chain all xattr_ref object. It's re-chained to
+        * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
+        */
+       ref->ino = je32_to_cpu(rr->ino);
+       ref->xid = je32_to_cpu(rr->xid);
+       ref->xseqno = je32_to_cpu(rr->xseqno);
+       if (ref->xseqno > c->highest_xseqno)
+               c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
+       ref->next = c->xref_temp;
+       c->xref_temp = ref;
+
+       jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
+
+       if (jffs2_sum_active())
+               jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
+       dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
+                 ofs, ref->xid, ref->ino);
+       return 0;
+}
+#endif
+
+/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
+   the flash, XIP-style */
 static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-                               unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
+                                 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
        struct jffs2_unknown_node *node;
        struct jffs2_unknown_node crcnode;
-       struct jffs2_sum_marker *sm;
        uint32_t ofs, prevofs;
        uint32_t hdr_crc, buf_ofs, buf_len;
        int err;
@@ -331,67 +450,102 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
        if (jffs2_cleanmarker_oob(c)) {
-               int ret = jffs2_check_nand_cleanmarker(c, jeb);
+               int ret;
+
+               if (c->mtd->block_isbad(c->mtd, jeb->offset))
+                       return BLK_STATE_BADBLOCK;
+
+               ret = jffs2_check_nand_cleanmarker(c, jeb);
                D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret));
+
                /* Even if it's not found, we still scan to see
                   if the block is empty. We use this information
                   to decide whether to erase it or not. */
                switch (ret) {
                case 0:         cleanmarkerfound = 1; break;
                case 1:         break;
-               case 2:         return BLK_STATE_BADBLOCK;
-               case 3:         return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */
                default:        return ret;
                }
        }
 #endif
 
        if (jffs2_sum_active()) {
-               sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL);
-               if (!sm) {
-                       return -ENOMEM;
-               }
-
-               err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
-                                       sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
-               if (err) {
-                       kfree(sm);
-                       return err;
-               }
-
-               if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) {
-                       err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random);
-                       if (err) {
-                               kfree(sm);
+               struct jffs2_sum_marker *sm;
+               void *sumptr = NULL;
+               uint32_t sumlen;
+             
+               if (!buf_size) {
+                       /* XIP case. Just look, point at the summary if it's there */
+                       sm = (void *)buf + c->sector_size - sizeof(*sm);
+                       if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
+                               sumptr = buf + je32_to_cpu(sm->offset);
+                               sumlen = c->sector_size - je32_to_cpu(sm->offset);
+                       }
+               } else {
+                       /* If NAND flash, read a whole page of it. Else just the end */
+                       if (c->wbuf_pagesize)
+                               buf_len = c->wbuf_pagesize;
+                       else
+                               buf_len = sizeof(*sm);
+
+                       /* Read as much as we want into the _end_ of the preallocated buffer */
+                       err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, 
+                                                 jeb->offset + c->sector_size - buf_len,
+                                                 buf_len);                             
+                       if (err)
                                return err;
+
+                       sm = (void *)buf + buf_size - sizeof(*sm);
+                       if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
+                               sumlen = c->sector_size - je32_to_cpu(sm->offset);
+                               sumptr = buf + buf_size - sumlen;
+
+                               /* Now, make sure the summary itself is available */
+                               if (sumlen > buf_size) {
+                                       /* Need to kmalloc for this. */
+                                       sumptr = kmalloc(sumlen, GFP_KERNEL);
+                                       if (!sumptr)
+                                               return -ENOMEM;
+                                       memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
+                               }
+                               if (buf_len < sumlen) {
+                                       /* Need to read more so that the entire summary node is present */
+                                       err = jffs2_fill_scan_buf(c, sumptr, 
+                                                                 jeb->offset + c->sector_size - sumlen,
+                                                                 sumlen - buf_len);                            
+                                       if (err)
+                                               return err;
+                               }
                        }
+
                }
 
-               kfree(sm);
+               if (sumptr) {
+                       err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
 
-               ofs = jeb->offset;
-               prevofs = jeb->offset - 1;
+                       if (buf_size && sumlen > buf_size)
+                               kfree(sumptr);
+                       /* If it returns with a real error, bail. 
+                          If it returns positive, that's a block classification
+                          (i.e. BLK_STATE_xxx) so return that too.
+                          If it returns zero, fall through to full scan. */
+                       if (err)
+                               return err;
+               }
        }
 
        buf_ofs = jeb->offset;
 
        if (!buf_size) {
+               /* This is the XIP case -- we're reading _directly_ from the flash chip */
                buf_len = c->sector_size;
-
-               if (jffs2_sum_active()) {
-                       /* must reread because of summary test */
-                       err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
-                       if (err)
-                               return err;
-               }
-
        } else {
                buf_len = EMPTY_SCAN_SIZE(c->sector_size);
                err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
                if (err)
                        return err;
        }
-       
+
        /* We temporarily use 'ofs' as a pointer into the buffer/jeb */
        ofs = 0;
 
@@ -421,7 +575,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
        if (ofs) {
                D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
                          jeb->offset + ofs));
-               DIRTY_SPACE(ofs);
+               if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
+                       return err;
+               if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
+                       return err;
        }
 
        /* Now ofs is a complete physical flash offset as it always was... */
@@ -431,11 +588,16 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
 
        dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset);
 
-scan_more:     
+scan_more:
        while(ofs < jeb->offset + c->sector_size) {
 
                jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 
+               /* Make sure there are node refs available for use */
+               err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+               if (err)
+                       return err;
+
                cond_resched();
 
                if (ofs & 3) {
@@ -445,7 +607,8 @@ scan_more:
                }
                if (ofs == prevofs) {
                        printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs);
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -454,7 +617,8 @@ scan_more:
                if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
                        D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node),
                                  jeb->offset, c->sector_size, ofs, sizeof(*node)));
-                       DIRTY_SPACE((jeb->offset + c->sector_size)-ofs);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
+                               return err;
                        break;
                }
 
@@ -472,19 +636,21 @@ scan_more:
 
                if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
                        uint32_t inbuf_ofs;
-                       uint32_t empty_start;
+                       uint32_t empty_start, scan_end;
 
                        empty_start = ofs;
                        ofs += 4;
+                       scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len);
 
                        D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs));
                more_empty:
                        inbuf_ofs = ofs - buf_ofs;
-                       while (inbuf_ofs < buf_len) {
-                               if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
+                       while (inbuf_ofs < scan_end) {
+                               if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) {
                                        printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
                                               empty_start, ofs);
-                                       DIRTY_SPACE(ofs-empty_start);
+                                       if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
+                                               return err;
                                        goto scan_more;
                                }
 
@@ -496,21 +662,27 @@ scan_more:
 
                        /* If we're only checking the beginning of a block with a cleanmarker,
                           bail now */
-                       if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && 
-                           c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) {
+                       if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
+                           c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
                                D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
                                return BLK_STATE_CLEANMARKER;
                        }
-
+                       if (!buf_size && (scan_end != buf_len)) {/* XIP/point case */
+                               scan_end = buf_len;
+                               goto more_empty;
+                       }
+                       
                        /* See how much more there is to read in this eraseblock... */
                        buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
                        if (!buf_len) {
-                               /* No more to read. Break out of main loop without marking 
+                               /* No more to read. Break out of main loop without marking
                                   this range of empty space as dirty (because it's not) */
                                D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space\n",
                                          empty_start));
                                break;
                        }
+                       /* point never reaches here */
+                       scan_end = buf_len;
                        D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs));
                        err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
                        if (err)
@@ -521,29 +693,33 @@ scan_more:
 
                if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
                        printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs);
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
                if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
                        D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs));
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
                if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
                        printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);
                        printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
                if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) {
                        /* OK. We're out of possibilities. Whinge and move on */
-                       noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", 
-                                    JFFS2_MAGIC_BITMASK, ofs, 
+                       noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n",
+                                    JFFS2_MAGIC_BITMASK, ofs,
                                     je16_to_cpu(node->magic));
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -556,22 +732,23 @@ scan_more:
                if (hdr_crc != je32_to_cpu(node->hdr_crc)) {
                        noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n",
                                     ofs, je16_to_cpu(node->magic),
-                                    je16_to_cpu(node->nodetype), 
+                                    je16_to_cpu(node->nodetype),
                                     je32_to_cpu(node->totlen),
                                     je32_to_cpu(node->hdr_crc),
                                     hdr_crc);
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
 
-               if (ofs + je32_to_cpu(node->totlen) > 
-                   jeb->offset + c->sector_size) {
+               if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) {
                        /* Eep. Node goes over the end of the erase block. */
                        printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
                               ofs, je32_to_cpu(node->totlen));
                        printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -579,7 +756,8 @@ scan_more:
                if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
                        /* Wheee. This is an obsoleted node */
                        D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
-                       DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                               return err;
                        ofs += PAD(je32_to_cpu(node->totlen));
                        continue;
                }
@@ -600,7 +778,7 @@ scan_more:
                        if (err) return err;
                        ofs += PAD(je32_to_cpu(node->totlen));
                        break;
-                       
+
                case JFFS2_NODETYPE_DIRENT:
                        if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
                                buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
@@ -617,30 +795,59 @@ scan_more:
                        ofs += PAD(je32_to_cpu(node->totlen));
                        break;
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+               case JFFS2_NODETYPE_XATTR:
+                       if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+                               buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+                               D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
+                                         " left to end of buf. Reading 0x%x at 0x%08x\n",
+                                         je32_to_cpu(node->totlen), buf_len, ofs));
+                               err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+                               if (err)
+                                       return err;
+                               buf_ofs = ofs;
+                               node = (void *)buf;
+                       }
+                       err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
+                       if (err)
+                               return err;
+                       ofs += PAD(je32_to_cpu(node->totlen));
+                       break;
+               case JFFS2_NODETYPE_XREF:
+                       if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+                               buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+                               D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
+                                         " left to end of buf. Reading 0x%x at 0x%08x\n",
+                                         je32_to_cpu(node->totlen), buf_len, ofs));
+                               err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+                               if (err)
+                                       return err;
+                               buf_ofs = ofs;
+                               node = (void *)buf;
+                       }
+                       err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
+                       if (err)
+                               return err;
+                       ofs += PAD(je32_to_cpu(node->totlen));
+                       break;
+#endif /* CONFIG_JFFS2_FS_XATTR */
+
                case JFFS2_NODETYPE_CLEANMARKER:
                        D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
                        if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
-                               printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", 
+                               printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
                                       ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
-                               DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
+                                       return err;
                                ofs += PAD(sizeof(struct jffs2_unknown_node));
                        } else if (jeb->first_node) {
                                printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
-                               DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
+                                       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->next_in_ino = NULL;
-                               marker_ref->next_phys = NULL;
-                               marker_ref->flash_offset = ofs | REF_NORMAL;
-                               marker_ref->__totlen = c->cleanmarker_size;
-                               jeb->first_node = jeb->last_node = marker_ref;
-                            
-                               USED_SPACE(PAD(c->cleanmarker_size));
+                               jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
+
                                ofs += PAD(c->cleanmarker_size);
                        }
                        break;
@@ -648,7 +855,8 @@ scan_more:
                case JFFS2_NODETYPE_PADDING:
                        if (jffs2_sum_active())
                                jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
-                       DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                               return err;
                        ofs += PAD(je32_to_cpu(node->totlen));
                        break;
 
@@ -656,10 +864,11 @@ scan_more:
                        switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
                        case JFFS2_FEATURE_ROCOMPAT:
                                printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);
-                               c->flags |= JFFS2_SB_FLAG_RO;
+                               c->flags |= JFFS2_SB_FLAG_RO;
                                if (!(jffs2_is_readonly(c)))
                                        return -EROFS;
-                               DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                                       return err;
                                ofs += PAD(je32_to_cpu(node->totlen));
                                break;
 
@@ -669,15 +878,21 @@ scan_more:
 
                        case JFFS2_FEATURE_RWCOMPAT_DELETE:
                                D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-                               DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                                       return err;
                                ofs += PAD(je32_to_cpu(node->totlen));
                                break;
 
-                       case JFFS2_FEATURE_RWCOMPAT_COPY:
+                       case JFFS2_FEATURE_RWCOMPAT_COPY: {
                                D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-                               USED_SPACE(PAD(je32_to_cpu(node->totlen)));
+
+                               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);
                                ofs += PAD(je32_to_cpu(node->totlen));
                                break;
+                               }
                        }
                }
        }
@@ -690,9 +905,9 @@ scan_more:
                }
        }
 
-       D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, 
-                 jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size));
-
+       D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
+                 jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
+       
        /* mark_node_obsolete can add to wasted !! */
        if (jeb->wasted_size) {
                jeb->dirty_size += jeb->wasted_size;
@@ -726,79 +941,58 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
        ic->nodes = (void *)ic;
        jffs2_add_ino_cache(c, ic);
        if (ino == 1)
-               ic->nlink = 1;
+               ic->pino_nlink = 1;
        return ic;
 }
 
-static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 
+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);
+       uint32_t crc, ino = je32_to_cpu(ri->ino);
 
        D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
 
        /* We do very little here now. Just check the ino# to which we should attribute
-          this node; we can do all the CRC checking etc. later. There's a tradeoff here -- 
+          this node; we can do all the CRC checking etc. later. There's a tradeoff here --
           we used to scan the flash once only, reading everything we want from it into
           memory, then building all our in-core data structures and freeing the extra
           information. Now we allow the first part of the mount to complete a lot quicker,
-          but we have to go _back_ to the flash in order to finish the CRC checking, etc. 
+          but we have to go _back_ to the flash in order to finish the CRC checking, etc.
           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;
+       /* Check the node CRC in any case. */
+       crc = crc32(0, ri, sizeof(*ri)-8);
+       if (crc != je32_to_cpu(ri->node_crc)) {
+               printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on "
+                      "node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+                      ofs, je32_to_cpu(ri->node_crc), crc);
+               /*
+                * We believe totlen because the CRC on the node
+                * _header_ was OK, just the node itself failed.
+                */
+               return jffs2_scan_dirty_space(c, jeb,
+                                             PAD(je32_to_cpu(ri->totlen)));
        }
 
        ic = jffs2_get_ino_cache(c, ino);
        if (!ic) {
-               /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
-                  first node we found for this inode. Do a CRC check to protect against the former
-                  case */
-               uint32_t crc = crc32(0, ri, sizeof(*ri)-8);
-
-               if (crc != je32_to_cpu(ri->node_crc)) {
-                       printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
-                              ofs, je32_to_cpu(ri->node_crc), crc);
-                       /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-                       DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
-                       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 */
+       jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
 
-       raw->flash_offset = ofs | REF_UNCHECKED;
-       raw->__totlen = PAD(je32_to_cpu(ri->totlen));
-       raw->next_phys = NULL;
-       raw->next_in_ino = ic->nodes;
-
-       ic->nodes = raw;
-       if (!jeb->first_node)
-               jeb->first_node = raw;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = raw;
-       jeb->last_node = raw;
-
-       D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", 
+       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),
                  je32_to_cpu(ri->offset),
                  je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize)));
 
        pseudo_random += je32_to_cpu(ri->version);
 
-       UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
-
        if (jffs2_sum_active()) {
                jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
        }
@@ -806,13 +1000,14 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
        return 0;
 }
 
-static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 
+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 checkedlen;
        uint32_t crc;
+       int err;
 
        D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));
 
@@ -824,61 +1019,52 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
                printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
                       ofs, je32_to_cpu(rd->node_crc), crc);
                /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-               DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
+               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
+                       return err;
                return 0;
        }
 
        pseudo_random += je32_to_cpu(rd->version);
 
-       fd = jffs2_alloc_full_dirent(rd->nsize+1);
+       /* Should never happen. Did. (OLPC trac #4184)*/
+       checkedlen = strnlen(rd->name, rd->nsize);
+       if (checkedlen < rd->nsize) {
+               printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars\n",
+                      ofs, checkedlen);
+       }
+       fd = jffs2_alloc_full_dirent(checkedlen+1);
        if (!fd) {
                return -ENOMEM;
        }
-       memcpy(&fd->name, rd->name, rd->nsize);
-       fd->name[rd->nsize] = 0;
+       memcpy(&fd->name, rd->name, checkedlen);
+       fd->name[checkedlen] = 0;
 
        crc = crc32(0, fd->name, rd->nsize);
        if (crc != je32_to_cpu(rd->name_crc)) {
                printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
-                      ofs, je32_to_cpu(rd->name_crc), crc);    
+                      ofs, je32_to_cpu(rd->name_crc), crc);
                D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino)));
                jffs2_free_full_dirent(fd);
                /* FIXME: Why do we believe totlen? */
                /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
-               DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
+               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
+                       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->__totlen = PAD(je32_to_cpu(rd->totlen));
-       raw->flash_offset = ofs | REF_PRISTINE;
-       raw->next_phys = NULL;
-       raw->next_in_ino = ic->nodes;
-       ic->nodes = raw;
-       if (!jeb->first_node)
-               jeb->first_node = raw;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = raw;
-       jeb->last_node = raw;
-
-       fd->raw = raw;
+
+       fd->raw = jffs2_link_node_ref(c, jeb, ofs | dirent_node_state(rd),
+                                     PAD(je32_to_cpu(rd->totlen)), ic);
+
        fd->next = NULL;
        fd->version = je32_to_cpu(rd->version);
        fd->ino = je32_to_cpu(rd->ino);
-       fd->nhash = full_name_hash(fd->name, rd->nsize);
+       fd->nhash = full_name_hash(fd->name, checkedlen);
        fd->type = rd->type;
-       USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
        jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
        if (jffs2_sum_active()) {