[PATCH] jffs2: Fix garbage collection when jffs2_read_dnode() returns EIO

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I am by no means certain that this is the correct fix for the problem
at hand but it seems to work for us.

/Kim

---

For unknown reasons a jffs2 partition had entered a state where it would
not function properly (e.g. writing new files would abort) and give log
messages like:
  jffs2: Data CRC 178b4d59 != calculated CRC 22902b28 for node at 011425d0
  jffs2: read_cache_page() returned error: -5
  jffs2: Error garbage collecting node at 01141f88!

The file system was effectively unusable until the file containing the
offending node(s) was deleted.

The "Data CRC" message is issued by jffs2_read_dnode() which returns
-EIO (= -5).
The problem in our case first manifests itself during garbage collection
after mount where the call tree in reverse order is:
                  jffs2_read_dnode() -> EIO
                jffs2_read_inode_range() -> EIO
              jffs2_do_readpage_nolock() -> EIO
            jffs2_do_readpage_unlock() -> EIO
          read_cache_page() -> EIO
        jffs2_gc_fetch_page() -> EIO
      jffs2_garbage_collect_dnode() -> EIO
    jffs2_garbage_collect_live() -> EIO
  jffs2_garbage_collect_pass() -> ENOSPC
jffs2_garbage_collect_thread()

The garbage collection thread is then aborted:
  jffs2: No space for garbage collection. Aborting GC thread

This commit changes the behavior so that if jffs2_garbage_collect_live()
in jffs2_garbage_collect_pass() returns EIO, we obsolete the offending
node.
During subsequent GC passes this will clean up the file system to become
usable.

Signed-off-by: Kim Woelders <kw@xxxxxxxxx>

diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 9ed0f26cf023..25c075b3c189 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -470,7 +470,10 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 		/* Eep. This really should never happen. GC is broken */
 		pr_err("Error garbage collecting node at %08x!\n",
 		       ref_offset(jeb->gc_node));
-		ret = -ENOSPC;
+		if (ret == -EIO)
+			jffs2_mark_node_obsolete(c, raw);
+		else
+			ret = -ENOSPC;
 	}
  release_sem:
 	mutex_unlock(&c->alloc_sem);
-- 
2.17.2


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux