All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhe Li <lizhe67@huawei.com>
To: <dwmw2@infradead.org>, <richard@nod.at>, <wenwen@cs.uga.edu>,
	<linux-mtd@lists.infradead.org>, <linux-kernel@vger.kernel.org>
Cc: <yihuaijie@huawei.com>
Subject: [PATCH] jffs2: fix jffs2 mounting failure
Date: Thu, 9 Apr 2020 17:11:34 +0800	[thread overview]
Message-ID: <20200409091134.61364-1-lizhe67@huawei.com> (raw)

There is a scene that may easily case mounting failure while using
nand flash with jffs2. The steps are listed below.
1.erase nand flash
2.mount jffs2 on it (this mounting operation will be successful)
3.do chown or chmod to the mount point directory
4.umount jffs2
5.mount jffs2 on nand flash
Step 5 will return I/O ERROR

The reason for this mounting failure is that at the end of function
jffs2_scan_medium(), jffs2 will check the used_size and some info
of nr_blocks.If conditions are met, it will return -EIO.

In the steps listed above, step 3 will write jffs2_raw_inode into
flash without jffs2_raw_dirent, which will cause that there are some
jffs2_raw_inode but no jffs2_raw_dirent on flash. This will meet
the condition at the end of function jffs2_scan_medium() and return
-EIO if we umount jffs2 and mount it again.

Typical image of this problem is like:
Empty space found from 0x00000000 to 0x008a0000
Inode node at xx, totlen 0x00000044, #ino 1, version 1, isize 0...

This patch add a flag to fix this problem. Appropriate bits of the
flag will be set if we scan a jffs2_raw_inode with ino != 1 and
ino == 1. And the flag will be check at the judgment of return
-EIO,which is mentioned above.

Signed-off-by: Zhe Li <lizhe67@huawei.com>
---
 fs/jffs2/build.c       |  1 +
 fs/jffs2/jffs2_fs_sb.h | 26 ++++++++++++++++++++++++++
 fs/jffs2/scan.c        |  8 +++++++-
 3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index b288c8a..d9fda40 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -405,6 +405,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
 	INIT_LIST_HEAD(&c->bad_used_list);
 	c->highest_ino = 1;
 	c->summary = NULL;
+	c->inode_flag = INODE_FLAG_INIT;
 
 	ret = jffs2_sum_init(c);
 	if (ret)
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 778275f..a01b5f4 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -27,6 +27,10 @@
 #define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */
 #define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */
 
+#define INODE_FLAG_INIT 0
+#define INODE_FLAG_HAS_ROOT_INODE  (0x01 << 0)
+#define INODE_FLAG_HAS_OTHER_INODE (0x01 << 1)
+
 struct jffs2_inodirty;
 
 struct jffs2_mount_opts {
@@ -157,6 +161,28 @@ struct jffs2_sb_info {
 #endif
 	/* OS-private pointer for getting back to master superblock info */
 	void *os_priv;
+	/* this flag show the contained inodes info */
+	int inode_flag;
 };
 
+static inline void set_root_inode_flag(struct jffs2_sb_info *c)
+{
+	c->inode_flag |= INODE_FLAG_HAS_ROOT_INODE;
+}
+
+static inline void set_other_inode_flag(struct jffs2_sb_info *c)
+{
+	c->inode_flag |= INODE_FLAG_HAS_OTHER_INODE;
+}
+
+static inline int has_root_inode(struct jffs2_sb_info *c)
+{
+	return (c->inode_flag & INODE_FLAG_HAS_ROOT_INODE);
+}
+
+static inline int has_other_inode(struct jffs2_sb_info *c)
+{
+	return (c->inode_flag & INODE_FLAG_HAS_OTHER_INODE);
+}
+
 #endif /* _JFFS2_FS_SB */
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 5f7e284..ec13e08 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -261,7 +261,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
 	}
 #endif
 	if (c->nr_erasing_blocks) {
-		if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
+		if (!c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks) != c->nr_blocks || bad_blocks == c->nr_blocks) &&
+		    !(has_root_inode(c) && !has_other_inode(c))) {
 			pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
 			pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",
 				  empty_blocks, bad_blocks, c->nr_blocks);
@@ -1036,6 +1037,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
 		jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
 	}
 
+	if (likely(ino != 1))
+		set_other_inode_flag(c);
+	else
+		set_root_inode_flag(c);
+
 	return 0;
 }
 
-- 
2.7.4


WARNING: multiple messages have this Message-ID (diff)
From: Zhe Li <lizhe67@huawei.com>
To: <dwmw2@infradead.org>, <richard@nod.at>, <wenwen@cs.uga.edu>,
	<linux-mtd@lists.infradead.org>, <linux-kernel@vger.kernel.org>
Cc: yihuaijie@huawei.com
Subject: [PATCH] jffs2: fix jffs2 mounting failure
Date: Thu, 9 Apr 2020 17:11:34 +0800	[thread overview]
Message-ID: <20200409091134.61364-1-lizhe67@huawei.com> (raw)

There is a scene that may easily case mounting failure while using
nand flash with jffs2. The steps are listed below.
1.erase nand flash
2.mount jffs2 on it (this mounting operation will be successful)
3.do chown or chmod to the mount point directory
4.umount jffs2
5.mount jffs2 on nand flash
Step 5 will return I/O ERROR

The reason for this mounting failure is that at the end of function
jffs2_scan_medium(), jffs2 will check the used_size and some info
of nr_blocks.If conditions are met, it will return -EIO.

In the steps listed above, step 3 will write jffs2_raw_inode into
flash without jffs2_raw_dirent, which will cause that there are some
jffs2_raw_inode but no jffs2_raw_dirent on flash. This will meet
the condition at the end of function jffs2_scan_medium() and return
-EIO if we umount jffs2 and mount it again.

Typical image of this problem is like:
Empty space found from 0x00000000 to 0x008a0000
Inode node at xx, totlen 0x00000044, #ino 1, version 1, isize 0...

This patch add a flag to fix this problem. Appropriate bits of the
flag will be set if we scan a jffs2_raw_inode with ino != 1 and
ino == 1. And the flag will be check at the judgment of return
-EIO,which is mentioned above.

Signed-off-by: Zhe Li <lizhe67@huawei.com>
---
 fs/jffs2/build.c       |  1 +
 fs/jffs2/jffs2_fs_sb.h | 26 ++++++++++++++++++++++++++
 fs/jffs2/scan.c        |  8 +++++++-
 3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index b288c8a..d9fda40 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -405,6 +405,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
 	INIT_LIST_HEAD(&c->bad_used_list);
 	c->highest_ino = 1;
 	c->summary = NULL;
+	c->inode_flag = INODE_FLAG_INIT;
 
 	ret = jffs2_sum_init(c);
 	if (ret)
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 778275f..a01b5f4 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -27,6 +27,10 @@
 #define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */
 #define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */
 
+#define INODE_FLAG_INIT 0
+#define INODE_FLAG_HAS_ROOT_INODE  (0x01 << 0)
+#define INODE_FLAG_HAS_OTHER_INODE (0x01 << 1)
+
 struct jffs2_inodirty;
 
 struct jffs2_mount_opts {
@@ -157,6 +161,28 @@ struct jffs2_sb_info {
 #endif
 	/* OS-private pointer for getting back to master superblock info */
 	void *os_priv;
+	/* this flag show the contained inodes info */
+	int inode_flag;
 };
 
+static inline void set_root_inode_flag(struct jffs2_sb_info *c)
+{
+	c->inode_flag |= INODE_FLAG_HAS_ROOT_INODE;
+}
+
+static inline void set_other_inode_flag(struct jffs2_sb_info *c)
+{
+	c->inode_flag |= INODE_FLAG_HAS_OTHER_INODE;
+}
+
+static inline int has_root_inode(struct jffs2_sb_info *c)
+{
+	return (c->inode_flag & INODE_FLAG_HAS_ROOT_INODE);
+}
+
+static inline int has_other_inode(struct jffs2_sb_info *c)
+{
+	return (c->inode_flag & INODE_FLAG_HAS_OTHER_INODE);
+}
+
 #endif /* _JFFS2_FS_SB */
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 5f7e284..ec13e08 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -261,7 +261,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
 	}
 #endif
 	if (c->nr_erasing_blocks) {
-		if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
+		if (!c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks) != c->nr_blocks || bad_blocks == c->nr_blocks) &&
+		    !(has_root_inode(c) && !has_other_inode(c))) {
 			pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
 			pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",
 				  empty_blocks, bad_blocks, c->nr_blocks);
@@ -1036,6 +1037,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
 		jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
 	}
 
+	if (likely(ino != 1))
+		set_other_inode_flag(c);
+	else
+		set_root_inode_flag(c);
+
 	return 0;
 }
 
-- 
2.7.4


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

             reply	other threads:[~2020-04-09  9:12 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-09  9:11 Zhe Li [this message]
2020-04-09  9:11 ` [PATCH] jffs2: fix jffs2 mounting failure Zhe Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200409091134.61364-1-lizhe67@huawei.com \
    --to=lizhe67@huawei.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=richard@nod.at \
    --cc=wenwen@cs.uga.edu \
    --cc=yihuaijie@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.