]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - fs/jffs2/readinode.c
Merge git://git.infradead.org/~dwmw2/rbtree-2.6
[linux-2.6.git] / fs / jffs2 / readinode.c
index e6076fa5560f5c0a3b112bb5c56c21c70313e570..5fec012b02ed59a1fa5f8ca871849af4c24e4e40 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: readinode.c,v 1.137 2005/08/03 09:26:46 dedekind Exp $
+ * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $
  *
  */
 
@@ -66,7 +66,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
                        jffs2_free_full_dnode(tn->fn);
                        jffs2_free_tmp_dnode_info(tn);
 
-                       this = this->rb_parent;
+                       this = rb_parent(this);
                        if (!this)
                                break;
 
@@ -97,7 +97,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
        while (ref && ref->next_in_ino) {
                if (!ref_obsolete(ref))
                        return ref;
-               JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
+               dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
                ref = ref->next_in_ino;
        }
        return NULL;
@@ -112,23 +112,46 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
  *         negative error code on failure.
  */
 static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
-                               struct jffs2_raw_dirent *rd, uint32_t read, struct jffs2_full_dirent **fdp,
+                               struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp,
                                uint32_t *latest_mctime, uint32_t *mctime_ver)
 {
        struct jffs2_full_dirent *fd;
-       
-       /* The direntry nodes are checked during the flash scanning */
-       BUG_ON(ref_flags(ref) == REF_UNCHECKED);
+       uint32_t crc;
+
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
        BUG_ON(ref_obsolete(ref));
-                       
-       /* Sanity check */
-       if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
-               JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
-                      ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
+
+       crc = crc32(0, rd, sizeof(*rd) - 8);
+       if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
+               JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
+                            ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
                return 1;
        }
-       
+
+       /* If we've never checked the CRCs on this node, check them now */
+       if (ref_flags(ref) == REF_UNCHECKED) {
+               struct jffs2_eraseblock *jeb;
+               int len;
+
+               /* Sanity check */
+               if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
+                       JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
+                                   ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
+                       return 1;
+               }
+
+               jeb = &c->blocks[ref->flash_offset / c->sector_size];
+               len = ref_totlen(c, jeb, ref);
+
+               spin_lock(&c->erase_completion_lock);
+               jeb->used_size += len;
+               jeb->unchecked_size -= len;
+               c->used_size += len;
+               c->unchecked_size -= len;
+               ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
+               spin_unlock(&c->erase_completion_lock);
+       }
+
        fd = jffs2_alloc_full_dirent(rd->nsize + 1);
        if (unlikely(!fd))
                return -ENOMEM;
@@ -139,44 +162,44 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
        fd->type = rd->type;
 
        /* Pick out the mctime of the latest dirent */
-       if(fd->version > *mctime_ver) {
+       if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) {
                *mctime_ver = fd->version;
                *latest_mctime = je32_to_cpu(rd->mctime);
        }
 
-       /* 
+       /*
         * Copy as much of the name as possible from the raw
         * dirent we've already read from the flash.
         */
        if (read > sizeof(*rd))
                memcpy(&fd->name[0], &rd->name[0],
                       min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
-               
+
        /* Do we need to copy any more of the name directly from the flash? */
        if (rd->nsize + sizeof(*rd) > read) {
                /* FIXME: point() */
                int err;
                int already = read - sizeof(*rd);
-                       
-               err = jffs2_flash_read(c, (ref_offset(ref)) + read, 
+
+               err = jffs2_flash_read(c, (ref_offset(ref)) + read,
                                rd->nsize - already, &read, &fd->name[already]);
                if (unlikely(read != rd->nsize - already) && likely(!err))
                        return -EIO;
-                       
+
                if (unlikely(err)) {
                        JFFS2_ERROR("read remainder of name: error %d\n", err);
                        jffs2_free_full_dirent(fd);
                        return -EIO;
                }
        }
-       
+
        fd->nhash = full_name_hash(fd->name, rd->nsize);
        fd->next = NULL;
        fd->name[rd->nsize] = '\0';
-       
+
        /*
         * Wheee. We now have a complete jffs2_full_dirent structure, with
-        * the name in it and everything. Link it into the list 
+        * the name in it and everything. Link it into the list
         */
        jffs2_add_fd_to_list(c, fd, fdp);
 
@@ -198,30 +221,30 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        struct jffs2_tmp_dnode_info *tn;
        uint32_t len, csize;
        int ret = 1;
-       
+       uint32_t crc;
+
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
        BUG_ON(ref_obsolete(ref));
 
+       crc = crc32(0, rd, sizeof(*rd) - 8);
+       if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
+               JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
+                            ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
+               return 1;
+       }
+
        tn = jffs2_alloc_tmp_dnode_info();
        if (!tn) {
-               JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn));
+               JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
                return -ENOMEM;
        }
 
        tn->partial_crc = 0;
        csize = je32_to_cpu(rd->csize);
-       
+
        /* If we've never checked the CRCs on this node, check them now */
        if (ref_flags(ref) == REF_UNCHECKED) {
-               uint32_t crc;
 
-               crc = crc32(0, rd, sizeof(*rd) - 8);
-               if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
-                       JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
-                                       ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
-                       goto free_out;
-               }
-               
                /* Sanity checks */
                if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
                    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
@@ -272,13 +295,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                        buf = (unsigned char *)rd + sizeof(*rd);
                        /* len will be the read data length */
                        len = min_t(uint32_t, rdlen - sizeof(*rd), csize);
-                       
-                       if (len)
-                               tn->partial_crc = crc = crc32(0, buf, len);
+                       tn->partial_crc = crc32(0, buf, len);
+
+                       dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize);
 
                        /* If we actually calculated the whole data CRC
                         * and it is wrong, drop the node. */
-                       if (len == csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
+                       if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
                                JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
                                        ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
                                goto free_out;
@@ -293,7 +316,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                         */
                        struct jffs2_eraseblock *jeb;
 
-                       JFFS2_DBG_READINODE("the node has no data.\n");
+                       dbg_readinode("the node has no data.\n");
                        jeb = &c->blocks[ref->flash_offset / c->sector_size];
                        len = ref_totlen(c, jeb, ref);
 
@@ -313,13 +336,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                ret = -ENOMEM;
                goto free_out;
        }
-       
+
        tn->version = je32_to_cpu(rd->version);
        tn->fn->ofs = je32_to_cpu(rd->offset);
        tn->data_crc = je32_to_cpu(rd->data_crc);
        tn->csize = csize;
        tn->fn->raw = ref;
-       
+
        /* There was a bug where we wrote hole nodes out with
           csize/dsize swapped. Deal with it */
        if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize)
@@ -327,9 +350,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        else // normal case...
                tn->fn->size = je32_to_cpu(rd->dsize);
 
-       JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n",
-                 ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize));
-       
+       dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
+                 ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
+
        jffs2_add_tn_to_tree(tn, tnp);
 
        return 0;
@@ -343,7 +366,7 @@ free_out:
  * Helper function for jffs2_get_inode_nodes().
  * It is called every time an unknown node is found.
  *
- * Returns: 0 on succes;
+ * Returns: 0 on success;
  *         1 if the node should be marked obsolete;
  *         negative error code on failure.
  */
@@ -351,40 +374,33 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
 {
        /* We don't mark unknown nodes as REF_UNCHECKED */
        BUG_ON(ref_flags(ref) == REF_UNCHECKED);
-       
+
        un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
 
-       if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
-               /* Hmmm. This should have been caught at scan time. */
-               JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
-               jffs2_dbg_dump_node(c, ref_offset(ref));
-               return 1;
-       } else {
-               switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
+       switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
 
-               case JFFS2_FEATURE_INCOMPAT:
-                       JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
-                               je16_to_cpu(un->nodetype), ref_offset(ref));
-                       /* EEP */
-                       BUG();
-                       break;
+       case JFFS2_FEATURE_INCOMPAT:
+               JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
+                           je16_to_cpu(un->nodetype), ref_offset(ref));
+               /* EEP */
+               BUG();
+               break;
 
-               case JFFS2_FEATURE_ROCOMPAT:
-                       JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
-                                       je16_to_cpu(un->nodetype), ref_offset(ref));
-                       BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
-                       break;
+       case JFFS2_FEATURE_ROCOMPAT:
+               JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
+                           je16_to_cpu(un->nodetype), ref_offset(ref));
+               BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
+               break;
 
-               case JFFS2_FEATURE_RWCOMPAT_COPY:
-                       JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
-                                       je16_to_cpu(un->nodetype), ref_offset(ref));
-                       break;
+       case JFFS2_FEATURE_RWCOMPAT_COPY:
+               JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
+                            je16_to_cpu(un->nodetype), ref_offset(ref));
+               break;
 
-               case JFFS2_FEATURE_RWCOMPAT_DELETE:
-                       JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
-                                       je16_to_cpu(un->nodetype), ref_offset(ref));
-                       return 1;
-               }
+       case JFFS2_FEATURE_RWCOMPAT_DELETE:
+               JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
+                            je16_to_cpu(un->nodetype), ref_offset(ref));
+               return 1;
        }
 
        return 0;
@@ -423,8 +439,8 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
                bufstart = buf + *rdlen;
                len = right_size - *rdlen;
        }
-       
-       JFFS2_DBG_READINODE("read more %d bytes.", len);
+
+       dbg_readinode("read more %d bytes\n", len);
 
        err = jffs2_flash_read(c, offs, len, &retlen, bufstart);
        if (err) {
@@ -432,9 +448,9 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
                        "error code: %d.\n", len, offs, err);
                return err;
        }
-       
+
        if (retlen < len) {
-               JFFS2_ERROR("short read at %#08x: %d instead of %d.\n",
+               JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
                                offs, retlen, len);
                return -EIO;
        }
@@ -460,8 +476,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
        int len, err;
 
        *mctime_ver = 0;
-       
-       JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino);
+
+       dbg_readinode("ino #%u\n", f->inocache->ino);
 
        if (jffs2_is_writebuffered(c)) {
                /*
@@ -487,7 +503,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
        buf = kmalloc(len, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
-                       
+
        spin_lock(&c->erase_completion_lock);
        valid_ref = jffs2_first_valid_node(f->inocache->nodes);
        if (!valid_ref && f->inocache->ino != 1)
@@ -514,7 +530,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                 * size = JFFS2_MIN_NODE_HEADER.
                 */
                if (jffs2_is_writebuffered(c)) {
-                       /* 
+                       /*
                         * We treat 'buf' as 2 adjacent wbufs. We want to
                         * adjust bufstart such as it points to the
                         * beginning of the node within this wbuf.
@@ -531,7 +547,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                        len = JFFS2_MIN_NODE_HEADER;
                }
 
-               JFFS2_DBG_READINODE("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
+               dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
 
                /* FIXME: point() */
                err = jffs2_flash_read(c, ref_offset(ref), len,
@@ -540,17 +556,29 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                        JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err);
                        goto free_out;
                }
-               
+
                if (retlen < len) {
-                       JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len);
+                       JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
                        err = -EIO;
                        goto free_out;
                }
-               
+
                node = (union jffs2_node_union *)bufstart;
-                       
+
+               /* No need to mask in the valid bit; it shouldn't be invalid */
+               if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
+                       JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
+                                    ref_offset(ref), je16_to_cpu(node->u.magic),
+                                    je16_to_cpu(node->u.nodetype),
+                                    je32_to_cpu(node->u.totlen),
+                                    je32_to_cpu(node->u.hdr_crc));
+                       jffs2_dbg_dump_node(c, ref_offset(ref));
+                       jffs2_mark_node_obsolete(c, ref);
+                       goto cont;
+               }
+
                switch (je16_to_cpu(node->u.nodetype)) {
-                       
+
                case JFFS2_NODETYPE_DIRENT:
 
                        if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
@@ -558,21 +586,21 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                                if (unlikely(err))
                                        goto free_out;
                        }
-                       
+
                        err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver);
                        if (err == 1) {
                                jffs2_mark_node_obsolete(c, ref);
                                break;
                        } else if (unlikely(err))
                                goto free_out;
-                       
+
                        if (je32_to_cpu(node->d.version) > *highest_version)
                                *highest_version = je32_to_cpu(node->d.version);
 
                        break;
 
                case JFFS2_NODETYPE_INODE:
-                       
+
                        if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
                                err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart);
                                if (unlikely(err))
@@ -588,7 +616,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
 
                        if (je32_to_cpu(node->i.version) > *highest_version)
                                *highest_version = je32_to_cpu(node->i.version);
-                       
+
                        break;
 
                default:
@@ -597,7 +625,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                                if (unlikely(err))
                                        goto free_out;
                        }
-                       
+
                        err = read_unknown(c, ref, &node->u);
                        if (err == 1) {
                                jffs2_mark_node_obsolete(c, ref);
@@ -606,6 +634,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                                goto free_out;
 
                }
+       cont:
                spin_lock(&c->erase_completion_lock);
        }
 
@@ -614,7 +643,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
        *fdp = ret_fd;
        kfree(buf);
 
-       JFFS2_DBG_READINODE("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
+       dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
                        f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver);
        return 0;
 
@@ -625,7 +654,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
        return err;
 }
 
-static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, 
+static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                                        struct jffs2_inode_info *f,
                                        struct jffs2_raw_inode *latest_node)
 {
@@ -639,7 +668,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
        size_t retlen;
        int ret;
 
-       JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
+       dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
 
        /* Grab all nodes relevant to this ino */
        ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
@@ -659,7 +688,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
                fn = tn->fn;
                ret = 1;
-               JFFS2_DBG_READINODE("consider node ver %u, phys offset "
+               dbg_readinode("consider node ver %u, phys offset "
                        "%#08x(%d), range %u-%u.\n", tn->version,
                        ref_offset(fn->raw), ref_flags(fn->raw),
                        fn->ofs, fn->ofs + fn->size);
@@ -677,14 +706,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                        ret = 0; /* Prevent freeing the metadata update node */
                } else
                        jffs2_mark_node_obsolete(c, fn->raw);
-                       
+
                BUG_ON(rb->rb_left);
-               if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
+               if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
                        /* We were then left-hand child of our parent. We need
                         * to move our own right-hand child into our place. */
                        repl_rb = rb->rb_right;
                        if (repl_rb)
-                               repl_rb->rb_parent = rb->rb_parent;
+                               rb_set_parent(repl_rb, rb_parent(rb));
                } else
                        repl_rb = NULL;
 
@@ -692,18 +721,18 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 
                /* Remove the spent tn from the tree; don't bother rebalancing
                 * but put our right-hand child in our own place. */
-               if (tn->rb.rb_parent) {
-                       if (tn->rb.rb_parent->rb_left == &tn->rb)
-                               tn->rb.rb_parent->rb_left = repl_rb;
-                       else if (tn->rb.rb_parent->rb_right == &tn->rb)
-                               tn->rb.rb_parent->rb_right = repl_rb;
+               if (rb_parent(&tn->rb)) {
+                       if (rb_parent(&tn->rb)->rb_left == &tn->rb)
+                               rb_parent(&tn->rb)->rb_left = repl_rb;
+                       else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
+                               rb_parent(&tn->rb)->rb_right = repl_rb;
                        else BUG();
                } else if (tn->rb.rb_right)
-                       tn->rb.rb_right->rb_parent = NULL;
+                       rb_set_parent(tn->rb.rb_right, NULL);
 
                jffs2_free_tmp_dnode_info(tn);
                if (ret) {
-                       JFFS2_DBG_READINODE("delete dnode %u-%u.\n",
+                       dbg_readinode("delete dnode %u-%u.\n",
                                fn->ofs, fn->ofs + fn->size);
                        jffs2_free_full_dnode(fn);
                }
@@ -763,7 +792,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                }
                break;
 
-                       
+
        case S_IFREG:
                /* If it was a regular file, truncate it to the latest node's isize */
                jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
@@ -788,10 +817,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                                jffs2_do_clear_inode(c, f);
                                return -ENOMEM;
                        }
-                       
+
                        ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
                                                je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
-                       
+
                        if (ret  || retlen != je32_to_cpu(latest_node->csize)) {
                                if (retlen != je32_to_cpu(latest_node->csize))
                                        ret = -EIO;
@@ -803,9 +832,9 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                        }
 
                        f->target[je32_to_cpu(latest_node->csize)] = '\0';
-                       JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target);
+                       dbg_readinode("symlink's target '%s' cached\n", f->target);
                }
-               
+
                /* fall through... */
 
        case S_IFBLK:
@@ -848,10 +877,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 }
 
 /* Scan the list of all nodes present for this ino, build map of versions, etc. */
-int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 
+int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                        uint32_t ino, struct jffs2_raw_inode *latest_node)
 {
-       JFFS2_DBG_READINODE("read inode #%u\n", ino);
+       dbg_readinode("read inode #%u\n", ino);
 
  retry_inocache:
        spin_lock(&c->inocache_lock);
@@ -864,13 +893,13 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                case INO_STATE_CHECKEDABSENT:
                        f->inocache->state = INO_STATE_READING;
                        break;
-                       
+
                case INO_STATE_CHECKING:
                case INO_STATE_GC:
                        /* If it's in either of these states, we need
                           to wait for whoever's got it to finish and
                           put it back. */
-                       JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state);
+                       dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state);
                        sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
                        goto retry_inocache;
 
@@ -897,7 +926,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                        JFFS2_ERROR("cannot allocate inocache for root inode\n");
                        return -ENOMEM;
                }
-               JFFS2_DBG_READINODE("creating inocache for root inode\n");
+               dbg_readinode("creating inocache for root inode\n");
                memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
                f->inocache->ino = f->inocache->nlink = 1;
                f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
@@ -957,7 +986,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
                kfree(f->target);
                f->target = NULL;
        }
-       
+
        fds = f->dents;
        while(fds) {
                fd = fds;