git » libjio » commit 9090b4e

This patch fixes several small things in jtrans_rollback():

author Alberto Bertogli
2004-07-22 13:31:02 UTC
committer Alberto Bertogli
2007-07-15 13:16:57 UTC
parent 6577dfa1782dde14d0957f4f545137bf1990a2bc

This patch fixes several small things in jtrans_rollback():

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.

libjio.h +1 -0
trans.c +32 -14

diff --git a/libjio.h b/libjio.h
index f4477b4..bfae927 100644
--- a/libjio.h
+++ b/libjio.h
@@ -140,6 +140,7 @@ FILE *jfsopen(struct jfs *stream, const char *mode);
 /* 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 */
diff --git a/trans.c b/trans.c
index 2d91594..0258939 100644
--- a/trans.c
+++ b/trans.c
@@ -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;
 }
 
 /*