changeset 843:5427f4e9dcb6

objstore: implement a attach/detach objver to txn helpers This rewrites the previous logic that tried to keep track of minimum truncation size. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Fri, 16 Dec 2022 19:46:24 -0500
parents b0852eac72a9
children 77fd01b82fd7
files src/objstore/include/nomad/objstore_backend.h src/objstore/obj.c src/objstore/obj_txn.c src/objstore/objstore_impl.h
diffstat 4 files changed, 74 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/objstore/include/nomad/objstore_backend.h	Thu Dec 15 23:22:15 2022 -0500
+++ b/src/objstore/include/nomad/objstore_backend.h	Fri Dec 16 19:46:24 2022 -0500
@@ -91,11 +91,12 @@
 	 */
 	struct objstore_open_obj_info *open[2];
 
+	/* transaction related state */
 	struct {
-		uint64_t cookie;
-
-		/* setattr */
-		uint64_t min_size; /* the shorted truncation */
+		struct txn *txn;	 /* active txn */
+		int refcnt;		 /* number of attaches */
+		struct objver *prev_ver; /* version we cow'd from */
+		uint64_t min_data_size;	 /* the shortest truncation so far */
 	} txn;
 
 	/* misc */
--- a/src/objstore/obj.c	Thu Dec 15 23:22:15 2022 -0500
+++ b/src/objstore/obj.c	Fri Dec 16 19:46:24 2022 -0500
@@ -112,8 +112,10 @@
 	ver->private = NULL;
 	for (i = 0; i < ARRAY_LEN(ver->open); i++)
 		ver->open[i] = NULL;
-	ver->txn.cookie = UINT64_MAX;
-	ver->txn.min_size = 0;
+	ver->txn.txn = NULL;
+	ver->txn.refcnt = 0;
+	ver->txn.prev_ver = NULL;
+	ver->txn.min_data_size = 0;
 	ver->obj = NULL;
 
 	page_cache_init_objver(ver);
@@ -131,6 +133,9 @@
 	if (!ver)
 		return;
 
+	ASSERT3P(ver->txn.txn, ==, NULL);
+	ASSERT3S(ver->txn.refcnt, ==, 0);
+
 	/* we shouldn't be freeing open objects */
 	for (i = 0; i < ARRAY_LEN(ver->open); i++)
 		ASSERT3P(ver->open[i], ==, NULL);
@@ -498,6 +503,8 @@
 	/* clear cow status */
 	open->cow.needed = false;
 
+	txn_detach_objver(txn, new);
+
 	return 0;
 }
 
@@ -516,6 +523,8 @@
 	ASSERT3P(old->open[false], ==, open);
 	ASSERT3P(new->open[false], ==, NULL);
 
+	txn_detach_objver(txn, new);
+
 	objver_free(new);
 }
 
@@ -528,9 +537,9 @@
 	struct objver *old;
 	int ret;
 
-	reset_objver_txn_info(txn, open->ver);
+	old = open->ver;
 
-	old = open->ver;
+	ASSERT3P(old->txn.txn, ==, NULL);
 
 	if (!open->cow.needed)
 		return old;
@@ -548,8 +557,9 @@
 	new->obj = open->obj;
 	new->clock = new_clock;
 	new->attrs = old->attrs;
-	new->txn.cookie = old->txn.cookie;
-	new->txn.min_size = old->txn.min_size;
+
+	txn_attach_objver(txn, new);
+	new->txn.prev_ver = old;
 
 	/* add a txn entry */
 	entry = txn_alloc_entry(txn);
--- a/src/objstore/obj_txn.c	Thu Dec 15 23:22:15 2022 -0500
+++ b/src/objstore/obj_txn.c	Fri Dec 16 19:46:24 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
@@ -64,8 +64,6 @@
 	size_t orig_len;
 	int ret;
 
-	reset_objver_txn_info(NULL, ver);
-
 	if (offset >= ver->attrs.size)
 		return 0;
 
@@ -98,10 +96,15 @@
 static int __obj_setattr_perform(struct txn *txn, struct txn_entry *entry)
 {
 	struct objver *ver = entry->setattr.ver;
+	int ret;
 
-	return ver->obj->ops->setattr(ver,
-				      &ver->attrs,
-				      entry->setattr.changed);
+	ret = ver->obj->ops->setattr(ver,
+				     &ver->attrs,
+				     entry->setattr.changed);
+
+	txn_detach_objver(txn, ver);
+
+	return ret;
 }
 
 static void __obj_setattr_cleanup(struct txn *txn, struct txn_entry *entry)
@@ -109,6 +112,8 @@
 	struct objver *ver = entry->setattr.ver;
 
 	ver->attrs = entry->setattr.old_attrs;
+
+	txn_detach_objver(txn, ver);
 }
 
 void obj_setattr(struct txn *txn, struct objver *ver, const struct nattr *attrs,
@@ -116,7 +121,7 @@
 {
 	struct txn_entry *entry;
 
-	reset_objver_txn_info(txn, ver);
+	txn_attach_objver(txn, ver);
 
 	if (valid & OBJ_ATTR_SIZE) {
 		const uint64_t old = p2roundup(ver->attrs.size, PAGE_SIZE);
@@ -127,8 +132,9 @@
 			page_inval_range(ver, new / PAGE_SIZE,
 					 (old - new) / PAGE_SIZE);
 
-		/* keep track of the shortest truncation */
-		ver->txn.min_size = MIN(ver->txn.min_size, attrs->size);
+		/* keep track of the shortest truncation so far */
+		ver->txn.min_data_size = MIN(ver->txn.min_data_size,
+					     attrs->size);
 	}
 
 	entry = txn_alloc_entry(txn);
@@ -194,12 +200,16 @@
 		page_unlock(page);
 	}
 
+	txn_detach_objver(txn, ver);
+
 	return 0;
 
 err:
 	/* drop the remaining dirty pages */
 	page_inval_range(ver, pgno, last_pgno - pgno + 1);
 
+	txn_detach_objver(txn, ver);
+
 	return ret;
 }
 
@@ -208,6 +218,8 @@
 	/* drop the dirty pages */
 	page_inval_range(entry->write.ver, entry->write.pgno,
 			 entry->write.pgcnt);
+
+	txn_detach_objver(txn, entry->write.ver);
 }
 
 /* write an arbitrary number of bytes */
@@ -222,7 +234,7 @@
 	ASSERT3U(offset, <, ver->attrs.size);
 	ASSERT3U(offset + len, <=, ver->attrs.size);
 
-	reset_objver_txn_info(txn, ver);
+	txn_attach_objver(txn, ver);
 
 	entry = txn_alloc_entry(txn);
 	entry->op = OP_WRITE;
--- a/src/objstore/objstore_impl.h	Thu Dec 15 23:22:15 2022 -0500
+++ b/src/objstore/objstore_impl.h	Fri Dec 16 19:46:24 2022 -0500
@@ -135,6 +135,37 @@
 	return err;
 }
 
+static inline void txn_attach_objver(struct txn *txn, struct objver *ver)
+{
+	if (ver->txn.txn == txn) {
+		ver->txn.refcnt++;
+		return; /* already attached */
+	}
+
+	ASSERT3P(ver->txn.txn, ==, NULL);
+	ASSERT3S(ver->txn.refcnt, ==, 0);
+
+	ver->txn.txn = txn;
+	ver->txn.refcnt = 1;
+	ver->txn.prev_ver = NULL;
+	ver->txn.min_data_size = ver->attrs.size;
+}
+
+static inline void txn_detach_objver(struct txn *txn, struct objver *ver)
+{
+	ASSERT3P(ver->txn.txn, ==, txn);
+	ASSERT3S(ver->txn.refcnt, >, 0);
+
+	ver->txn.refcnt--;
+	if (ver->txn.refcnt)
+		return;
+
+	ver->txn.txn = NULL;
+	ver->txn.refcnt = 0;
+	ver->txn.prev_ver = NULL;
+	ver->txn.min_data_size = 0;
+}
+
 /*
  * page-based cache
  */
@@ -150,17 +181,6 @@
 #define page_lock(page)		do { } while (0)
 #define page_unlock(page)	do { } while (0)
 
-static inline void reset_objver_txn_info(struct txn *txn, struct objver *ver)
-{
-	uint64_t cookie = txn ? txn->id : UINT64_MAX;
-
-	if (ver->txn.cookie == cookie)
-		return;
-
-	ver->txn.cookie = cookie;
-	ver->txn.min_size = ver->attrs.size;
-}
-
 REFCNT_INLINE_FXNS(struct obj, obj, refcnt, obj_free, NULL);
 
 #endif