WARNING followed by splat when running rewrite test program

OGAWA Hirofumi hirofumi at mail.parknet.co.jp
Mon May 5 08:56:35 PDT 2014


OGAWA Hirofumi <hirofumi at mail.parknet.co.jp> writes:

> [BTW, I'm trying to reproduce bug of tests/generic/299, but not succeed yet.]

I still can't reproduce this bug though. I found the bug in umount race.

The kernel core flusher can run after ->put_super() is called. If this
race happen, tux3 has possibility of crash or memory corruption.

The following patch will fix this bug.


Signed-off-by: OGAWA Hirofumi <hirofumi at mail.parknet.co.jp>
---

 user/kernel/commit.c    |   19 ++++++++++++++++---
 user/kernel/tux3.h      |    1 +
 user/kernel/writeback.c |    6 ++++++
 3 files changed, 23 insertions(+), 3 deletions(-)

diff -puN user/kernel/commit.c~wait-debug user/kernel/commit.c
--- tux3/user/kernel/commit.c~wait-debug	2014-05-06 00:09:12.306295035 +0900
+++ tux3-hirofumi/user/kernel/commit.c	2014-05-06 00:09:12.314295016 +0900
@@ -433,6 +433,19 @@ static int do_commit(struct sb *sb, enum
 	/* further changes of frontend belong to the next delta */
 	tux3_start_backend(sb);
 
+	/*
+	 * While umount, do_commit can race with umount. So, this
+	 * checks if need to commit or not. Otherwise, e.g. sb->logmap
+	 * can be freed already by ->put_super().
+	 *
+	 * And if sync/fsync() called, we may not have dirty inodes.
+	 *
+	 * FIXME: there is no need to commit if normal inodes are not
+	 * dirty? better way?
+	 */
+	if (!tux3_has_dirty_inodes(sb, delta))
+		goto out;
+
 	/* Prepare to wait I/O */
 	tux3_iowait_init(&iowait);
 	sb->iowait = &iowait;
@@ -454,13 +467,13 @@ static int do_commit(struct sb *sb, enum
 	 */
 	err = stage_delta(sb, delta);
 	if (err)
-		goto error; /* FIXME: error handling */
+		goto out; /* FIXME: error handling */
 
 	if ((unify_flag == ALLOW_UNIFY && need_unify(sb)) ||
 	    unify_flag == FORCE_UNIFY) {
 		err = unify_log(sb);
 		if (err)
-			goto error; /* FIXME: error handling */
+			goto out; /* FIXME: error handling */
 
 		/* Add delta log for debugging. */
 		log_delta(sb);
@@ -481,7 +494,7 @@ static int do_commit(struct sb *sb, enum
 	 * commit block.)
 	 */
 	commit_delta(sb);
-error:
+out:
 	/* FIXME: what to do if error? */
 	tux3_end_backend();
 	trace("<<<<<<<<< commit done %u: err %d", delta, err);
diff -puN user/kernel/tux3.h~wait-debug user/kernel/tux3.h
--- tux3/user/kernel/tux3.h~wait-debug	2014-05-06 00:09:12.306295035 +0900
+++ tux3-hirofumi/user/kernel/tux3.h	2014-05-06 00:09:12.314295016 +0900
@@ -993,6 +993,7 @@ int tux3_inode_is_orphan(struct tux3_ino
 int tux3_flush_inode_internal(struct inode *inode, unsigned delta, int req_flag);
 int tux3_flush_inode(struct inode *inode, unsigned delta, int req_flag);
 int tux3_flush_inodes(struct sb *sb, unsigned delta);
+int tux3_has_dirty_inodes(struct sb *sb, unsigned delta);
 void tux3_clear_dirty_inodes(struct sb *sb, unsigned delta);
 void tux3_check_destroy_inode_flags(struct inode *inode);
 
diff -puN user/kernel/writeback.c~wait-debug user/kernel/writeback.c
--- tux3/user/kernel/writeback.c~wait-debug	2014-05-06 00:09:12.310295024 +0900
+++ tux3-hirofumi/user/kernel/writeback.c	2014-05-06 00:09:12.314295016 +0900
@@ -666,6 +666,12 @@ error:
 	return err;
 }
 
+int tux3_has_dirty_inodes(struct sb *sb, unsigned delta)
+{
+	struct sb_delta_dirty *s_ddc = tux3_sb_ddc(sb, delta);
+	return !list_empty(&s_ddc->dirty_inodes);
+}
+
 /*
  * Clear inode dirty flags after flush.
  */
_

-- 
OGAWA Hirofumi <hirofumi at mail.parknet.co.jp>



More information about the Tux3 mailing list