author | Alberto Bertogli
<albertito@gmail.com> 2004-07-22 13:31:02 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-07-15 13:16:57 UTC |
parent | 6577dfa1782dde14d0957f4f545137bf1990a2bc |
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; } /*