[PATCH] eCryptfs: dput() lower d_parent on rename
[safe/jmp/linux-2.6] / fs / jffs2 / nodelist.c
index 0e82979..5a6b4d6 100644 (file)
@@ -21,6 +21,9 @@
 #include <linux/pagemap.h>
 #include "nodelist.h"
 
+static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,
+                                    struct jffs2_node_frag *this);
+
 void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list)
 {
        struct jffs2_full_dirent **prev = list;
@@ -87,7 +90,8 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint
        }
 }
 
-void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
+static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,
+                                    struct jffs2_node_frag *this)
 {
        if (this->node) {
                this->node->frags--;
@@ -906,6 +910,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
 {
        struct jffs2_inode_cache **prev;
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+       BUG_ON(old->xref);
+#endif
        dbg_inocache("del %p (ino #%u)\n", old, old->ino);
        spin_lock(&c->inocache_lock);
 
@@ -954,18 +961,16 @@ 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) {
-                       next = this->next_phys;
-                       __jffs2_free_raw_node_ref(this);
+                       if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
+                               next = this[REFS_PER_BLOCK].next_in_ino;
+                       else
+                               next = NULL;
+
+                       jffs2_free_refblock(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)
@@ -1060,32 +1065,37 @@ struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
 {
        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;
+       BUG_ON(!jeb->allocated_refs);
+       jeb->allocated_refs--;
+
+       ref = jeb->last_node;
+
+       dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
+                   ref->next_in_ino);
+
+       while (ref->flash_offset != REF_EMPTY_NODE) {
+               if (ref->flash_offset == REF_LINK_NODE)
+                       ref = ref->next_in_ino;
+               else
+                       ref++;
        }
 
-       ref->next_phys = NULL;
+       dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref, 
+                   ref->flash_offset, ofs, ref->next_in_ino, len);
+
        ref->flash_offset = ofs;
 
-       if (!jeb->first_node)
+       if (!jeb->first_node) {
                jeb->first_node = ref;
-       if (jeb->last_node) {
-               jeb->last_node->next_phys = ref;
-#ifdef TEST_TOTLEN
-               if (ref_offset(jeb->last_node) + jeb->last_node->__totlen != ref_offset(ref)) {
-                       printk(KERN_CRIT "Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
-                              ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
-                              ref_offset(jeb->last_node), ref_offset(jeb->last_node)+jeb->last_node->__totlen);
-                       WARN_ON(1);
-               }
-#endif
+               BUG_ON(ref_offset(ref) != jeb->offset);
+       } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
+               uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
+
+               JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
+                           ref, ref_offset(ref), ref_offset(ref)+len,
+                           ref_offset(jeb->last_node), 
+                           ref_offset(jeb->last_node)+last_len);
+               BUG();
        }
        jeb->last_node = ref;
 
@@ -1130,11 +1140,12 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
 {
        if (!size)
                return 0;
-       if (size > c->sector_size - jeb->used_size) {
-               printk(KERN_CRIT "Dirty space 0x%x larger then used_size 0x%x (wasted 0x%x)\n",
-                      size, jeb->used_size, jeb->wasted_size);
+       if (unlikely(size > jeb->free_size)) {
+               printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
+                      size, jeb->free_size, jeb->wasted_size);
                BUG();
        }
+       /* REF_EMPTY_NODE is !obsolete, so that works OK */
        if (jeb->last_node && ref_obsolete(jeb->last_node)) {
 #ifdef TEST_TOTLEN
                jeb->last_node->__totlen += size;
@@ -1168,7 +1179,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
                        jeb = &c->blocks[ref->flash_offset / c->sector_size];
 
                /* Last node in block. Use free_space */
-               if (ref != jeb->last_node) {
+               if (unlikely(ref != jeb->last_node)) {
                        printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
                               ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
                        BUG();
@@ -1183,17 +1194,13 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
 {
        uint32_t ret;
 
-#if CONFIG_JFFS2_FS_DEBUG > 0
-       if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
-               printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
-                      jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
-               BUG();
-       }
-#endif
-
        ret = __ref_totlen(c, jeb, ref);
+
 #ifdef TEST_TOTLEN
-       if (ret != ref->__totlen) {
+       if (unlikely(ret != ref->__totlen)) {
+               if (!jeb)
+                       jeb = &c->blocks[ref->flash_offset / c->sector_size];
+
                printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
                       ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
                       ret, ref->__totlen);
@@ -1204,13 +1211,14 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
                        printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);
 
                printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
-               ret = ref->__totlen;
-               if (!jeb)
-                       jeb = &c->blocks[ref->flash_offset / c->sector_size];
+
 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
                __jffs2_dbg_dump_node_refs_nolock(c, jeb);
 #endif
+
                WARN_ON(1);
+
+               ret = ref->__totlen;
        }
 #endif /* TEST_TOTLEN */
        return ret;