changeset 886:29d00736e18e

objstore: move the transaction structure to the heap This change will allow the transaction to outlive the caller. This will be necessary when we try to decouple the transaction commit from the completion. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Mon, 19 Dec 2022 19:21:21 -0500
parents a739778d0f6a
children 796345005f9f
files src/objstore/obj_ops.c src/objstore/objstore_impl.h src/objstore/txn.c
diffstat 3 files changed, 64 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/objstore/obj_ops.c	Sun Dec 18 11:53:21 2022 -0500
+++ b/src/objstore/obj_ops.c	Mon Dec 19 19:21:21 2022 -0500
@@ -190,7 +190,7 @@
 {
 	struct objver *newver;
 	struct obj *obj;
-	struct txn txn;
+	struct txn *txn;
 	int ret;
 
 	if (!open || !attr)
@@ -237,20 +237,24 @@
 	 * fire off the txn
 	 */
 
-	ret = txn_begin(&txn, obj->clone);
-	if (ret)
+	txn = txn_begin(obj->clone);
+	if (IS_ERR(txn)) {
+		ret = PTR_ERR(txn);
 		goto err;
+	}
 
-	newver = obj_cow(&txn, open);
+	newver = obj_cow(txn, open);
 	if (IS_ERR(newver)) {
 		ret = PTR_ERR(newver);
 		goto err_txn;
 	}
 
-	obj_setattr(&txn, newver, attr, valid);
+	obj_setattr(txn, newver, attr, valid);
+
+	ret = 0;
 
 err_txn:
-	ret = txn_commitabort(&txn, ret);
+	ret = txn_commitabort(txn, ret);
 	newver = NULL; /* prevent accidental use */
 
 	/* return current attributes */
@@ -301,7 +305,7 @@
 {
 	struct objver *newver;
 	struct obj *obj;
-	struct txn txn;
+	struct txn *txn;
 	ssize_t ret;
 
 	if (!open || !buf)
@@ -330,11 +334,13 @@
 	/*
 	 * fire off the txn
 	 */
-	ret = txn_begin(&txn, obj->clone);
-	if (ret)
+	txn = txn_begin(obj->clone);
+	if (IS_ERR(txn)) {
+		ret = PTR_ERR(txn);
 		goto err;
+	}
 
-	newver = obj_cow(&txn, open);
+	newver = obj_cow(txn, open);
 	if (IS_ERR(newver)) {
 		ret = PTR_ERR(newver);
 		goto err_txn;
@@ -346,18 +352,18 @@
 			.size = offset + len,
 		};
 
-		obj_setattr(&txn, newver, &attrs, OBJ_ATTR_SIZE);
+		obj_setattr(txn, newver, &attrs, OBJ_ATTR_SIZE);
 	}
 
-	ret = obj_write(&txn, newver, buf, len, offset);
+	ret = obj_write(txn, newver, buf, len, offset);
 
 err_txn:
 	if (ret < 0) {
-		txn_abort(&txn);
+		txn_abort(txn);
 	} else {
 		int ret2;
 
-		ret2 = txn_commit(&txn);
+		ret2 = txn_commit(txn);
 		if (ret2)
 			ret = ret2;
 	}
@@ -428,7 +434,7 @@
 {
 	struct objver *newver;
 	struct obj *dir;
-	struct txn txn;
+	struct txn *txn;
 	int ret;
 
 	if (!diropen || !name || !target)
@@ -450,20 +456,22 @@
 		goto err;
 	}
 
-	ret = txn_begin(&txn, diropen->ver->obj->clone);
-	if (ret)
+	txn = txn_begin(diropen->ver->obj->clone);
+	if (IS_ERR(txn)) {
+		ret = PTR_ERR(txn);
 		goto err;
+	}
 
-	newver = obj_cow(&txn, diropen);
+	newver = obj_cow(txn, diropen);
 	if (IS_ERR(newver)) {
 		ret = PTR_ERR(newver);
 		goto err_txn;
 	}
 
-	ret = dir_symlink(&txn, newver, name, owner, group, mode, target, child);
+	ret = dir_symlink(txn, newver, name, owner, group, mode, target, child);
 
 err_txn:
-	ret = txn_commitabort(&txn, ret);
+	ret = txn_commitabort(txn, ret);
 	newver = NULL; /* prevent accidental use */
 
 err:
@@ -483,7 +491,7 @@
 {
 	struct objver *newver;
 	struct obj *dir;
-	struct txn txn;
+	struct txn *txn;
 	int ret;
 
 	if (!diropen || !name)
@@ -501,20 +509,22 @@
 		goto err;
 	}
 
-	ret = txn_begin(&txn, diropen->ver->obj->clone);
-	if (ret)
+	txn = txn_begin(diropen->ver->obj->clone);
+	if (IS_ERR(txn)) {
+		ret = PTR_ERR(txn);
 		goto err;
+	}
 
-	newver = obj_cow(&txn, diropen);
+	newver = obj_cow(txn, diropen);
 	if (IS_ERR(newver)) {
 		ret = PTR_ERR(newver);
 		goto err_txn;
 	}
 
-	ret = dir_unlink(&txn, newver, name, desired, rmdir);
+	ret = dir_unlink(txn, newver, name, desired, rmdir);
 
 err_txn:
-	ret = txn_commitabort(&txn, ret);
+	ret = txn_commitabort(txn, ret);
 	newver = NULL; /* prevent accidental use */
 
 err:
@@ -529,7 +539,7 @@
 {
 	struct objver *newver;
 	struct obj *dir;
-	struct txn txn;
+	struct txn *txn;
 	int ret;
 
 	if (!diropen || !name || !child)
@@ -554,20 +564,22 @@
 		goto err;
 	}
 
-	ret = txn_begin(&txn, diropen->ver->obj->clone);
-	if (ret)
+	txn = txn_begin(diropen->ver->obj->clone);
+	if (IS_ERR(txn)) {
+		ret = PTR_ERR(txn);
 		goto err;
+	}
 
-	newver = obj_cow(&txn, diropen);
+	newver = obj_cow(txn, diropen);
 	if (IS_ERR(newver)) {
 		ret = PTR_ERR(newver);
 		goto err_txn;
 	}
 
-	ret = dir_create(&txn, newver, name, owner, group, mode, child);
+	ret = dir_create(txn, newver, name, owner, group, mode, child);
 
 err_txn:
-	ret = txn_commitabort(&txn, ret);
+	ret = txn_commitabort(txn, ret);
 	newver = NULL; /* prevent accidental use */
 
 err:
--- a/src/objstore/objstore_impl.h	Sun Dec 18 11:53:21 2022 -0500
+++ b/src/objstore/objstore_impl.h	Mon Dec 19 19:21:21 2022 -0500
@@ -123,7 +123,7 @@
  * entry as either fully initialized or as a no-op (OP_NOP).  Then, call
  * abort which will rollback up any non-nop entries.
  */
-extern int txn_begin(struct txn *txn, struct objstore_clone *clone);
+extern struct txn *txn_begin(struct objstore_clone *clone);
 extern int txn_commit(struct txn *txn);
 extern void txn_abort(struct txn *txn);
 extern struct txn_entry *txn_alloc_entry(struct txn *txn);
--- a/src/objstore/txn.c	Sun Dec 18 11:53:21 2022 -0500
+++ b/src/objstore/txn.c	Mon Dec 19 19:21:21 2022 -0500
@@ -107,11 +107,17 @@
  *    taken place.
  */
 
-int txn_begin(struct txn *txn, struct objstore_clone *clone)
+struct txn *txn_begin(struct objstore_clone *clone)
 {
 	static atomic64_t txn_ids;
+	struct txn *txn;
+	int ret;
 	int i;
 
+	txn = malloc(sizeof(struct txn));
+	if (!txn)
+		return ERR_PTR(-ENOMEM);
+
 	txn->id = atomic_inc(&txn_ids);
 	txn->clone = clone;
 
@@ -124,7 +130,16 @@
 		txn->entries[i].cleanup = NULL;
 	}
 
-	return clone->ops->txn_begin(txn);
+	ret = clone->ops->txn_begin(txn);
+	if (ret)
+		goto err;
+
+	return txn;
+
+err:
+	free(txn);
+
+	return ERR_PTR(ret);
 }
 
 static void txn_cleanup(struct txn *txn, bool complete)
@@ -170,6 +185,8 @@
 	}
 
 	memset(txn, 0x7c, sizeof(struct txn));
+
+	free(txn);
 }
 
 int txn_commit(struct txn *txn)