knfsd: various nfsd xdr cleanups
[powerpc.git] / fs / jffs2 / nodemgmt.c
index 71d1630..dbc908a 100644 (file)
@@ -1,14 +1,12 @@
 /*
  * 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: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $
- *
  */
 
 #include <linux/kernel.h>
@@ -172,6 +170,11 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
 static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
 
+       if (c->nextblock == NULL) {
+               D1(printk(KERN_DEBUG "jffs2_close_nextblock: Erase block at 0x%08x has already been placed in a list\n",
+                 jeb->offset));
+               return;
+       }
        /* Check, if we have a dirty block now, or if it was dirty already */
        if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
                c->dirty_size += jeb->wasted_size;
@@ -211,8 +214,7 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
                        struct jffs2_eraseblock *ejeb;
 
                        ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list);
-                       list_del(&ejeb->list);
-                       list_add_tail(&ejeb->list, &c->erase_pending_list);
+                       list_move_tail(&ejeb->list, &c->erase_pending_list);
                        c->nr_erasing_blocks++;
                        jffs2_erase_pending_trigger(c);
                        D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n",
@@ -317,6 +319,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                }
        } else {
                if (jeb && minsize > jeb->free_size) {
+                       uint32_t waste;
+
                        /* Skip the end of this block and file it as having some dirty space */
                        /* If there's a pending write to it, flush now */
 
@@ -329,10 +333,26 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                                goto restart;
                        }
 
-                       c->wasted_size += jeb->free_size;
-                       c->free_size -= jeb->free_size;
-                       jeb->wasted_size += jeb->free_size;
-                       jeb->free_size = 0;
+                       spin_unlock(&c->erase_completion_lock);
+
+                       ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+                       if (ret)
+                               return ret;
+                       /* Just lock it again and continue. Nothing much can change because
+                          we hold c->alloc_sem anyway. In fact, it's not entirely clear why
+                          we hold c->erase_completion_lock in the majority of this function...
+                          but that's a question for another (more caffeine-rich) day. */
+                       spin_lock(&c->erase_completion_lock);
+
+                       waste = jeb->free_size;
+                       jffs2_link_node_ref(c, jeb,
+                                           (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
+                                           waste, NULL);
+                       /* FIXME: that made it count as dirty. Convert to wasted */
+                       jeb->dirty_size -= waste;
+                       c->dirty_size -= waste;
+                       jeb->wasted_size += waste;
+                       c->wasted_size += waste;
 
                        jffs2_close_nextblock(c, jeb);
                        jeb = NULL;
@@ -666,19 +686,26 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                spin_lock(&c->erase_completion_lock);
 
                ic = jffs2_raw_ref_to_ic(ref);
-               /* It seems we should never call jffs2_mark_node_obsolete() for
-                  XATTR nodes.... yet. Make sure we notice if/when we change
-                  that :) */
-               BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
                for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
                        ;
 
                *p = ref->next_in_ino;
                ref->next_in_ino = NULL;
 
-               if (ic->nodes == (void *)ic && ic->nlink == 0)
-                       jffs2_del_ino_cache(c, ic);
-
+               switch (ic->class) {
+#ifdef CONFIG_JFFS2_FS_XATTR
+                       case RAWNODE_CLASS_XATTR_DATUM:
+                               jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
+                               break;
+                       case RAWNODE_CLASS_XATTR_REF:
+                               jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
+                               break;
+#endif
+                       default:
+                               if (ic->nodes == (void *)ic && ic->nlink == 0)
+                                       jffs2_del_ino_cache(c, ic);
+                               break;
+               }
                spin_unlock(&c->erase_completion_lock);
        }