Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[safe/jmp/linux-2.6] / fs / jffs2 / readinode.c
index 4cb4d76..d32ee94 100644 (file)
@@ -63,10 +63,11 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
        /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
         * adding and jffs2_flash_read_end() interface. */
        if (c->mtd->point) {
-               err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
+               err = c->mtd->point(c->mtd, ofs, len, &retlen,
+                                   (void **)&buffer, NULL);
                if (!err && retlen < len) {
                        JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
-                       c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
+                       c->mtd->unpoint(c->mtd, ofs, retlen);
                } else if (err)
                        JFFS2_WARNING("MTD point failed: error code %d.\n", err);
                else
@@ -100,7 +101,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
                kfree(buffer);
 #ifndef __ECOS
        else
-               c->mtd->unpoint(c->mtd, buffer, ofs, len);
+               c->mtd->unpoint(c->mtd, ofs, len);
 #endif
 
        if (crc != tn->data_crc) {
@@ -136,7 +137,7 @@ free_out:
                kfree(buffer);
 #ifndef __ECOS
        else
-               c->mtd->unpoint(c->mtd, buffer, ofs, len);
+               c->mtd->unpoint(c->mtd, ofs, len);
 #endif
        return err;
 }
@@ -219,7 +220,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                struct jffs2_tmp_dnode_info *tn)
 {
        uint32_t fn_end = tn->fn->ofs + tn->fn->size;
-       struct jffs2_tmp_dnode_info *this;
+       struct jffs2_tmp_dnode_info *this, *ptn;
 
        dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
 
@@ -250,11 +251,18 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
        if (this) {
                /* If the node is coincident with another at a lower address,
                   back up until the other node is found. It may be relevant */
-               while (this->overlapped)
-                       this = tn_prev(this);
-
-               /* First node should never be marked overlapped */
-               BUG_ON(!this);
+               while (this->overlapped) {
+                       ptn = tn_prev(this);
+                       if (!ptn) {
+                               /*
+                                * We killed a node which set the overlapped
+                                * flags during the scan. Fix it up.
+                                */
+                               this->overlapped = 0;
+                               break;
+                       }
+                       this = ptn;
+               }
                dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
        }
 
@@ -359,7 +367,17 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                        }
                        if (!this->overlapped)
                                break;
-                       this = tn_prev(this);
+
+                       ptn = tn_prev(this);
+                       if (!ptn) {
+                               /*
+                                * We killed a node which set the overlapped
+                                * flags during the scan. Fix it up.
+                                */
+                               this->overlapped = 0;
+                               break;
+                       }
+                       this = ptn;
                }
        }
 
@@ -455,8 +473,15 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
                eat_last(&rii->tn_root, &last->rb);
                ver_insert(&ver_root, last);
 
-               if (unlikely(last->overlapped))
-                       continue;
+               if (unlikely(last->overlapped)) {
+                       if (pen)
+                               continue;
+                       /*
+                        * We killed a node which set the overlapped
+                        * flags during the scan. Fix it up.
+                        */
+                       last->overlapped = 0;
+               }
 
                /* Now we have a bunch of nodes in reverse version
                   order, in the tree at ver_root. Most of the time,
@@ -542,7 +567,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
                        else BUG();
                }
        }
-       list->rb_node = NULL;
+       *list = RB_ROOT;
 }
 
 static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
@@ -906,7 +931,7 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
  * Helper function for jffs2_get_inode_nodes().
  * The function detects whether more data should be read and reads it if yes.
  *
- * Returns: 0 on succes;
+ * Returns: 0 on success;
  *         negative error code on failure.
  */
 static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -1123,7 +1148,8 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
        size_t retlen;
        int ret;
 
-       dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
+       dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino,
+                     f->inocache->pino_nlink);
 
        memset(&rii, 0, sizeof(rii));
 
@@ -1258,7 +1284,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                                f->target = NULL;
                                mutex_unlock(&f->sem);
                                jffs2_do_clear_inode(c, f);
-                               return -ret;
+                               return ret;
                        }
 
                        f->target[je32_to_cpu(latest_node->csize)] = '\0';
@@ -1358,7 +1384,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                }
                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->ino = f->inocache->pino_nlink = 1;
                f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
                f->inocache->state = INO_STATE_READING;
                jffs2_add_ino_cache(c, f->inocache);
@@ -1398,10 +1424,9 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
        struct jffs2_full_dirent *fd, *fds;
        int deleted;
 
-       jffs2_clear_acl(f);
        jffs2_xattr_delete_inode(c, f->inocache);
        mutex_lock(&f->sem);
-       deleted = f->inocache && !f->inocache->nlink;
+       deleted = f->inocache && !f->inocache->pino_nlink;
 
        if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);