changeset 857:a2e7e70338eb

objstore: rewrite obj_create to return the new object's objver This will allow us to perform other operations (e.g., write) on the newly allocated object in the same transation. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sat, 17 Dec 2022 13:29:59 -0500
parents eb4cc36f8ed1
children 6d515779ac45
files src/objstore/include/nomad/objstore_backend.h src/objstore/obj.c src/objstore/obj_dir_create.c src/objstore/objstore_impl.h
diffstat 4 files changed, 95 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/objstore/include/nomad/objstore_backend.h	Sat Dec 17 14:35:28 2022 -0500
+++ b/src/objstore/include/nomad/objstore_backend.h	Sat Dec 17 13:29:59 2022 -0500
@@ -146,10 +146,8 @@
 			struct objver *new;
 		} cow;
 		struct {
-			struct noid oid;
+			struct objver *ver;
 			struct noid parent;
-			struct nvclock clock;
-			struct nattr attrs;
 		} create;
 		struct {
 			struct objver *ver;
--- a/src/objstore/obj.c	Sat Dec 17 14:35:28 2022 -0500
+++ b/src/objstore/obj.c	Sat Dec 17 13:29:59 2022 -0500
@@ -476,34 +476,102 @@
 
 static int __obj_create_perform(struct txn *txn, struct txn_entry *entry)
 {
-	return txn->clone->ops->createobj(txn->clone,
-					  &entry->create.oid,
-					  &entry->create.clock,
-					  &entry->create.attrs,
-					  &entry->create.parent);
+	struct objver *ver = entry->create.ver;
+	int ret;
+
+	ret = txn->clone->ops->createobj(txn->clone,
+					 &ver->obj->oid,
+					 &ver->clock,
+					 &ver->attrs,
+					 &entry->create.parent);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void __obj_create_rollback(struct txn *txn, struct txn_entry *entry)
+{
+	panic("can't rollback transaction, must free obj");
+	/*
+	 * TODO: we must mark obj as dead and remove it from the
+	 * volume
+	 */
+}
+
+static void __obj_create_cleanup(struct txn *txn, struct txn_entry *entry)
+{
+	struct objver *ver = entry->create.ver;
+
+	txn_detach_objver(txn, ver);
+
+	MXUNLOCK(&ver->obj->lock);
+
+	obj_putref(ver->obj);
 }
 
-int obj_create(struct txn *txn, const struct nattr *attrs,
-	       struct noid *oid, const struct noid *parent)
+struct objver *obj_create(struct txn *txn, const struct nattr *attrs,
+			  const struct noid *parent)
 {
 	struct txn_entry *entry;
+	struct objver *ver;
+	struct obj *obj;
+	struct noid oid;
 	int ret;
 
-	ret = txn->clone->ops->allocoid(txn->clone, oid);
+	ret = txn->clone->ops->allocoid(txn->clone, &oid);
 	if (ret)
-		return ret;
+		return ERR_PTR(ret);
+
+	ASSERT(!noid_is_null(&oid));
+
+	/*
+	 * allocate a new object
+	 *
+	 * FIXME: triggers lockdep recursive locking warning (we're holding
+	 * the dir's lock and are trying to get the child's lock)
+	 */
+	obj = obj_by_oid(txn->clone, &oid, true);
+	if (IS_ERR(obj))
+		return ERR_CAST(obj);
+
+	/* allocate a new version - must match obj_add_version */
+	ver = objver_alloc();
+	if (IS_ERR(ver)) {
+		panic("failed to allocate objver, must free obj");
+		/*
+		 * TODO: we must mark obj as dead and remove it from the
+		 * volume
+		 */
+		MXUNLOCK(&obj->lock);
+		obj_putref(obj);
+		return ver;
+	}
+
+	ver->obj = obj;
+	VERIFY0(nvclock_inc(&ver->clock));
+	ver->attrs = *attrs;
+
+	/* associate the version with the new object */
+	rb_add(&obj->versions, ver);
+	__add_head(obj, ver);
+
+	txn_attach_objver(txn, ver);
+	ver->txn.min_data_size = 0; /* there is no data prior to creation */
+
+	/* get a reference for the txn entry */
+	obj_getref(obj);
 
 	entry = txn_alloc_entry(txn);
 	entry->op = OP_CREATE;
 	entry->perform = __obj_create_perform;
-	entry->create.oid = *oid;
-	nvclock_reset(&entry->create.clock);
-	VERIFY0(nvclock_inc(&entry->create.clock));
-	entry->create.attrs = *attrs;
+	entry->rollback = __obj_create_rollback;
+	entry->cleanup = __obj_create_cleanup;
+	entry->create.ver = ver;
 	entry->create.parent = *parent;
 	txn_log_entry(txn, entry);
 
-	return 0;
+	return ver;
 }
 
 static int __obj_cow_perform(struct txn *txn, struct txn_entry *entry)
--- a/src/objstore/obj_dir_create.c	Sat Dec 17 14:35:28 2022 -0500
+++ b/src/objstore/obj_dir_create.c	Sat Dec 17 13:29:59 2022 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright (c) 2015-2020,2022 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -41,8 +41,16 @@
 		.owner = owner,
 		.group = group,
 	};
+	struct objver *ver;
 
-	return obj_create(txn, &attrs, oid, parent);
+	ver = obj_create(txn, &attrs, parent);
+	if (IS_ERR(ver))
+		return PTR_ERR(ver);
+
+	*oid = ver->obj->oid;
+	obj_putref(ver->obj);
+
+	return 0;
 }
 
 static int __dir_create_add_dirent(struct txn *txn, struct objver *dirver,
--- a/src/objstore/objstore_impl.h	Sat Dec 17 14:35:28 2022 -0500
+++ b/src/objstore/objstore_impl.h	Sat Dec 17 13:29:59 2022 -0500
@@ -85,8 +85,8 @@
 /* add various transaction ops to the transaction */
 extern struct objver *obj_cow(struct txn *txn,
 			      struct objstore_open_obj_info *open);
-extern int obj_create(struct txn *txn, const struct nattr *attrs,
-		      struct noid *oid, const struct noid *parent);
+extern struct objver *obj_create(struct txn *txn, const struct nattr *attrs,
+				 const struct noid *parent);
 extern ssize_t obj_read(struct objver *ver, void *buf, size_t len,
 			uint64_t offset);
 extern void obj_setattr(struct txn *txn, struct objver *ver,