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