

This patch fixes several small things in jtrans_rollback():

* malloc() return value
* return -1 on error
* remove bogus comments
* free allocated memory
* don't allow more than one nested commit -> rollback

The last one avoids an endless loop that would cause
commit (failed) -> rollback -> commit (failed) -> rollback -> ...

by only allowing commit to call rollback once.


---

 cur-root/libjio.h |    1 +
 cur-root/trans.c  |   46 ++++++++++++++++++++++++++++++++--------------
 2 files changed, 33 insertions(+), 14 deletions(-)

diff -puN trans.c~rollback_fixes trans.c
--- cur/trans.c~rollback_fixes	2004-07-22 09:50:51.471622928 -0300
+++ cur-root/trans.c	2004-07-22 10:30:56.838951512 -0300
@@ -388,12 +388,17 @@ exit:
 		unlink(name);
 		free_tid(ts->fs, ts->id);
 
-		rv = ts->flags;
-		ts->flags = ts->flags | J_NOLOCK;
-		if (jtrans_rollback(ts) >= 0) {
-			ts->flags = rv | J_ROLLBACKED;
-		} else {
-			ts->flags = rv;
+		/* We want to avoid an endless loop of
+		 * commit (failed) -> rollback -> commit (failed)
+		 * so we use J_ROLLBACKING. */
+		if (!(ts->flags & J_ROLLBACKING)) {
+			rv = ts->flags;
+			ts->flags = ts->flags | J_NOLOCK | J_ROLLBACKING;
+			if (jtrans_rollback(ts) >= 0) {
+				ts->flags = rv | J_ROLLBACKED;
+			} else {
+				ts->flags = rv;
+			}
 		}
 	}
 
@@ -416,20 +421,18 @@ exit:
 /* rollback a transaction */
 int jtrans_rollback(struct jtrans *ts)
 {
+	int rv;
 	struct jtrans newts;
 	struct joper *op, *curop, *lop;
 
-	/* FIXME: this looks like a mess! */
+	jtrans_init(ts->fs, &newts);
+	newts.flags = ts->flags;
 
 	if (ts->op == NULL || ts->flags & J_NOROLLBACK) {
-		/* we're either trying to rollback an empty or transaction, or
-		 * a one marked without rollbacking support */
-		return 0;
+		rv = -1;
+		goto exit;
 	}
 
-	jtrans_init(ts->fs, &newts);
-	newts.flags = ts->flags;
-
 	/* find the last operation */
 	for (op = ts->op; op->next != NULL; op = op->next)
 		;
@@ -448,6 +451,11 @@ int jtrans_rollback(struct jtrans *ts)
 
 		/* manually add the operation to the new transaction */
 		curop = malloc(sizeof(struct joper));
+		if (curop == NULL) {
+			rv = -1;
+			goto exit;
+		}
+
 		curop->offset = op->offset;
 		curop->len = op->plen;
 		curop->buf = op->pdata;
@@ -469,7 +477,17 @@ int jtrans_rollback(struct jtrans *ts)
 		}
 	}
 
-	return jtrans_commit(&newts);
+	rv = jtrans_commit(&newts);
+
+exit:
+	/* free the transaction */
+	for (curop = newts.op; curop != NULL; curop = curop->next) {
+		curop->buf = NULL;
+		curop->pdata = NULL;
+	}
+	jtrans_free(&newts);
+
+	return rv;
 }
 
 /*
diff -puN libjio.h~rollback_fixes libjio.h
--- cur/libjio.h~rollback_fixes	2004-07-22 09:55:50.340188000 -0300
+++ cur-root/libjio.h	2004-07-22 09:56:26.119748680 -0300
@@ -140,6 +140,7 @@ FILE *jfsopen(struct jfs *stream, const 
 /* jtrans constants */
 #define J_COMMITED	1	/* mark a transaction as commited */
 #define J_ROLLBACKED	2	/* mark a transaction as rollbacked */
+#define J_ROLLBACKING	3	/* mark a transaction as rollbacking */
 
 /* disk constants */
 #define J_DISKHEADSIZE	 12	/* length of disk_header */
_

