[JFFS2] Prevent ino cache removal for inodes in use
David Woodhouse [Sun, 27 Feb 2005 23:01:36 +0000 (23:01 +0000)]
Don't remove inocache for inodes which are in read_inode() or
clear_inode() until they're done.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

fs/jffs2/erase.c
fs/jffs2/nodelist.c
fs/jffs2/nodelist.h
fs/jffs2/nodemgmt.c
fs/jffs2/readinode.c

index a3c6cc1..d1ae565 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: erase.c,v 1.71 2005/02/09 09:17:40 pavlov Exp $
+ * $Id: erase.c,v 1.72 2005/02/27 23:01:32 dwmw2 Exp $
  *
  */
 
@@ -277,11 +277,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
                printk("\n");
        });
 
-       if (ic->nodes == (void *)ic) {
-               D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));
+       if (ic->nodes == (void *)ic)
                jffs2_del_ino_cache(c, ic);
-               jffs2_free_inode_cache(ic);
-       }
 }
 
 static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
index 3c6d93c..b835a86 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodelist.c,v 1.92 2005/01/19 19:22:00 tpoynor Exp $
+ * $Id: nodelist.c,v 1.93 2005/02/27 23:01:32 dwmw2 Exp $
  *
  */
 
@@ -506,7 +506,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
 void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
 {
        struct jffs2_inode_cache **prev;
-       D2(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino));
+       D1(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino));
        spin_lock(&c->inocache_lock);
        
        prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];
@@ -518,6 +518,14 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
                *prev = old->next;
        }
 
+       /* Free it now unless it's in READING or CLEARING state, which
+          are the transitions upon read_inode() and clear_inode(). The
+          rest of the time we know nobody else is looking at it, and 
+          if it's held by read_inode() or clear_inode() they'll free it
+          for themselves. */
+       if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)
+               jffs2_free_inode_cache(old);
+
        spin_unlock(&c->inocache_lock);
 }
 
@@ -530,7 +538,6 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
                this = c->inocache_list[i];
                while (this) {
                        next = this->next;
-                       D2(printk(KERN_DEBUG "jffs2_free_ino_caches: Freeing ino #%u at %p\n", this->ino, this));
                        jffs2_free_inode_cache(this);
                        this = next;
                }
index 8c12283..57f675c 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodelist.h,v 1.127 2005/02/09 09:23:53 pavlov Exp $
+ * $Id: nodelist.h,v 1.128 2005/02/27 23:01:32 dwmw2 Exp $
  *
  */
 
@@ -135,6 +135,7 @@ struct jffs2_inode_cache {
 #define INO_STATE_CHECKEDABSENT        3       /* Checked, cleared again */
 #define INO_STATE_GC           4       /* GCing a 'pristine' node */
 #define INO_STATE_READING      5       /* In read_inode() */
+#define INO_STATE_CLEARING     6       /* In clear_inode() */
 
 #define INOCACHE_HASHSIZE 128
 
index 5e1e8ca..f9dcac1 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodemgmt.c,v 1.117 2005/01/25 20:11:11 hammache Exp $
+ * $Id: nodemgmt.c,v 1.118 2005/02/27 23:01:32 dwmw2 Exp $
  *
  */
 
@@ -593,11 +593,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                *p = ref->next_in_ino;
                ref->next_in_ino = NULL;
 
-               if (ic->nodes == (void *)ic) {
-                       D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));
+               if (ic->nodes == (void *)ic)
                        jffs2_del_ino_cache(c, ic);
-                       jffs2_free_inode_cache(ic);
-               }
 
                spin_unlock(&c->erase_completion_lock);
        }
index aca4a0b..a1980a9 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: readinode.c,v 1.117 2004/11/20 18:06:54 dwmw2 Exp $
+ * $Id: readinode.c,v 1.118 2005/02/27 23:01:33 dwmw2 Exp $
  *
  */
 
@@ -672,6 +672,9 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
        down(&f->sem);
        deleted = f->inocache && !f->inocache->nlink;
 
+       if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
+               jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
+
        if (f->metadata) {
                if (deleted)
                        jffs2_mark_node_obsolete(c, f->metadata->raw);
@@ -688,8 +691,11 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
                jffs2_free_full_dirent(fd);
        }
 
-       if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
+       if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
+               if (f->inocache->nodes == (void *)f->inocache)
+                       jffs2_del_ino_cache(c, f->inocache);
+       }
 
        up(&f->sem);
 }