jffs2: Fix garbage collection when jffs2_read_dnode() returns EIO
diff mbox series

Message ID 20181123125313.30041-1-kw@thrane.eu
State New
Delegated to: Richard Weinberger
Headers show
  • jffs2: Fix garbage collection when jffs2_read_dnode() returns EIO
Related show

Commit Message

Kim Woelders Nov. 23, 2018, 12:53 p.m. UTC

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



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

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
During subsequent GC passes this will clean up the file system to become

Signed-off-by: Kim Woelders <kw@thrane.eu>

diff mbox series

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",
-		ret = -ENOSPC;
+		if (ret == -EIO)
+			jffs2_mark_node_obsolete(c, raw);
+		else
+			ret = -ENOSPC;