changeset 862:9a63d933a60e

objstore: expose dirent add/update helpers to the rest of objstore These are useful anytime we want to create a new directory entry - create, link, symlink, etc. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sat, 17 Dec 2022 17:02:07 -0500
parents 9f4bd7cfa177
children 681892f1d3f7
files src/objstore/CMakeLists.txt src/objstore/dir.c src/objstore/dir.h src/objstore/obj_dir_create.c
diffstat 4 files changed, 181 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/src/objstore/CMakeLists.txt	Sat Dec 17 17:13:46 2022 -0500
+++ b/src/objstore/CMakeLists.txt	Sat Dec 17 17:02:07 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
@@ -22,6 +22,7 @@
 
 add_library(nomad_objstore SHARED
 	cache.c
+	dir.c
 	dirblock.c
 	dirent.c
 	dirent_target_packing.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/objstore/dir.c	Sat Dec 17 17:02:07 2022 -0500
@@ -0,0 +1,168 @@
+/*
+ * 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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "dir.h"
+
+int dir_add_dirent(struct txn *txn, struct objver *dirver, const char *name,
+		   uint16_t mode, const struct noid *child)
+{
+	uint8_t rawbuf[DIR_BLOCK_SIZE];
+	struct nattr attrs = {
+		.size = dirver->attrs.size + DIR_BLOCK_SIZE,
+	};
+	struct ndirent_tgt tgt;
+	struct dirblock block;
+	struct buffer buf;
+	ssize_t ret;
+
+	/* TODO: try to put it into an existing block */
+
+	buffer_init_static(&buf, rawbuf, 0, sizeof(rawbuf), true);
+
+	dirblock_init(&block);
+
+	tgt.type = mode >> NATTR_TSHIFT;
+	tgt.deleted = false;
+	tgt.host = noid_get_allocator(child);
+	tgt.uniq = noid_get_uniq(child);
+
+	ret = dirblock_add_dirent(&block, name, &tgt);
+	if (ret)
+		return ret;
+
+	ret = dirblock_serialize(&block, &buf);
+	if (ret)
+		return ret;
+
+	/* grow the directory by a block */
+	obj_setattr(txn, dirver, &attrs, OBJ_ATTR_SIZE);
+
+	/* fill in the fresh block */
+	ret = obj_write(txn, dirver, buffer_data(&buf), buffer_size(&buf),
+			dirver->attrs.size - DIR_BLOCK_SIZE);
+	if (ret < 0)
+		return ret;
+
+	if (ret != buffer_size(&buf))
+		panic("dir block partial write!");
+
+	return 0;
+}
+
+static int __dir_update_dirent(struct dirblock *block, const char *name,
+			       uint16_t mode, const struct noid *child)
+{
+	const size_t namelen = strlen(name);
+	size_t non_deleted_targets;
+	size_t i, j;
+
+	/* find the dirent */
+	for (i = 0; i < block->ndirents; i++) {
+		if (namelen != block->entries[i].dirent.namelen)
+			continue;
+
+		if (!strncmp(name, block->entries[i].name, namelen))
+			break;
+	}
+
+	VERIFY3U(i, <, block->ndirents);
+
+	VERIFY(block->entries[i].dirent.all_deleted);
+
+	/* find the target */
+	for (j = 0; j < block->entries[i].dirent.ntgts; j++) {
+		struct ndirent_tgt *tgt = &block->entries[i].tgts[j];
+
+		if ((tgt->host != noid_get_allocator(child)) ||
+		    (tgt->uniq != noid_get_uniq(child)))
+			continue;
+	}
+
+	/* update the target */
+	if (j < block->entries[i].dirent.ntgts) {
+		/* found a match - just reset the flag */
+		block->entries[i].tgts[j].deleted = false;
+	} else {
+		/* not found - allocate a new target */
+		struct ndirent_tgt tgt;
+		int ret;
+
+		tgt.type = mode >> NATTR_TSHIFT;
+		tgt.deleted = false;
+		tgt.host = noid_get_allocator(child);
+		tgt.uniq = noid_get_uniq(child);
+
+		ret = dirblock_add_dirent_target(block, name, &tgt);
+		if (ret)
+			return ret;
+	}
+
+	non_deleted_targets = 0;
+	for (j = 0; j < block->entries[i].dirent.ntgts; j++)
+		if (!block->entries[i].tgts[j].deleted)
+			non_deleted_targets++;
+
+	VERIFY3U(non_deleted_targets, ==, 1);
+
+	block->entries[i].dirent.conflicts = false;
+	block->entries[i].dirent.all_deleted = false;
+
+	return 0;
+}
+
+int dir_update_dirent(struct txn *txn, struct objver *dirver,
+		      uint8_t *raw, uint64_t diroff,
+		      uint16_t ndirents, const char *name,
+		      uint16_t mode, const struct noid *child)
+{
+	uint8_t rawbuf[DIR_BLOCK_SIZE];
+	struct dirblock block;
+	struct buffer buffer;
+	ssize_t ret;
+
+	/* parse the block */
+	ret = dirblock_parse(&block, raw, ndirents);
+	if (ret)
+		return ret;
+
+	/* update the dirent target */
+	ret = __dir_update_dirent(&block, name, mode, child);
+	if (ret)
+		return ret;
+
+	/* serialize the block & write it out */
+	buffer_init_static(&buffer, rawbuf, 0, sizeof(rawbuf), true);
+
+	ret = dirblock_serialize(&block, &buffer);
+	if (ret)
+		return ret;
+
+	ret = obj_write(txn, dirver, buffer_data(&buffer), buffer_size(&buffer),
+			diroff);
+	if (ret < 0)
+		return ret;
+
+	if (ret != buffer_size(&buffer))
+		panic("dir block partial write!");
+
+	return 0;
+}
--- a/src/objstore/dir.h	Sat Dec 17 17:13:46 2022 -0500
+++ b/src/objstore/dir.h	Sat Dec 17 17:02:07 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
@@ -217,6 +217,13 @@
 extern int dirblock_add_dirent_target(struct dirblock *block, const char *name,
 				      const struct ndirent_tgt *tgt);
 
+extern int dir_add_dirent(struct txn *txn, struct objver *dirver,
+			  const char *name, uint16_t mode,
+			  const struct noid *child);
+extern int dir_update_dirent(struct txn *txn, struct objver *dirver,
+			     uint8_t *raw, uint64_t diroff,
+			     uint16_t ndirents, const char *name,
+			     uint16_t mode, const struct noid *child);
 extern int dir_lookup_entry(struct objver *dirver, const char *name,
 			    uint8_t *raw, struct ndirent_mem *ent,
 			    uint64_t *_off, uint16_t *_ndirents);
--- a/src/objstore/obj_dir_create.c	Sat Dec 17 17:13:46 2022 -0500
+++ b/src/objstore/obj_dir_create.c	Sat Dec 17 17:02:07 2022 -0500
@@ -24,153 +24,6 @@
 
 #include <jeffpc/time.h>
 
-static int __dir_create_add_dirent(struct txn *txn, struct objver *dirver,
-				   const char *name, uint16_t mode,
-				   const struct noid *child)
-{
-	uint8_t rawbuf[DIR_BLOCK_SIZE];
-	struct nattr attrs = {
-		.size = dirver->attrs.size + DIR_BLOCK_SIZE,
-	};
-	struct ndirent_tgt tgt;
-	struct dirblock block;
-	struct buffer buf;
-	ssize_t ret;
-
-	/* TODO: try to put it into an existing block */
-
-	buffer_init_static(&buf, rawbuf, 0, sizeof(rawbuf), true);
-
-	dirblock_init(&block);
-
-	tgt.type = mode >> NATTR_TSHIFT;
-	tgt.deleted = false;
-	tgt.host = noid_get_allocator(child);
-	tgt.uniq = noid_get_uniq(child);
-
-	ret = dirblock_add_dirent(&block, name, &tgt);
-	if (ret)
-		return ret;
-
-	ret = dirblock_serialize(&block, &buf);
-	if (ret)
-		return ret;
-
-	/* grow the directory by a block */
-	obj_setattr(txn, dirver, &attrs, OBJ_ATTR_SIZE);
-
-	/* fill in the fresh block */
-	ret = obj_write(txn, dirver, buffer_data(&buf), buffer_size(&buf),
-			dirver->attrs.size - DIR_BLOCK_SIZE);
-	if (ret < 0)
-		return ret;
-
-	if (ret != buffer_size(&buf))
-		panic("dir block partial write!");
-
-	return 0;
-}
-
-static int __dir_create_update_dirent_real(struct dirblock *block,
-					   const char *name, uint16_t mode,
-					   const struct noid *child)
-{
-	const size_t namelen = strlen(name);
-	size_t non_deleted_targets;
-	size_t i, j;
-
-	/* find the dirent */
-	for (i = 0; i < block->ndirents; i++) {
-		if (namelen != block->entries[i].dirent.namelen)
-			continue;
-
-		if (!strncmp(name, block->entries[i].name, namelen))
-			break;
-	}
-
-	VERIFY3U(i, <, block->ndirents);
-
-	VERIFY(block->entries[i].dirent.all_deleted);
-
-	/* find the target */
-	for (j = 0; j < block->entries[i].dirent.ntgts; j++) {
-		struct ndirent_tgt *tgt = &block->entries[i].tgts[j];
-
-		if ((tgt->host != noid_get_allocator(child)) ||
-		    (tgt->uniq != noid_get_uniq(child)))
-			continue;
-	}
-
-	/* update the target */
-	if (j < block->entries[i].dirent.ntgts) {
-		/* found a match - just reset the flag */
-		block->entries[i].tgts[j].deleted = false;
-	} else {
-		/* not found - allocate a new target */
-		struct ndirent_tgt tgt;
-		int ret;
-
-		tgt.type = mode >> NATTR_TSHIFT;
-		tgt.deleted = false;
-		tgt.host = noid_get_allocator(child);
-		tgt.uniq = noid_get_uniq(child);
-
-		ret = dirblock_add_dirent_target(block, name, &tgt);
-		if (ret)
-			return ret;
-	}
-
-	non_deleted_targets = 0;
-	for (j = 0; j < block->entries[i].dirent.ntgts; j++)
-		if (!block->entries[i].tgts[j].deleted)
-			non_deleted_targets++;
-
-	VERIFY3U(non_deleted_targets, ==, 1);
-
-	block->entries[i].dirent.conflicts = false;
-	block->entries[i].dirent.all_deleted = false;
-
-	return 0;
-}
-
-static int __dir_create_update_dirent(struct txn *txn, struct objver *dirver,
-				      uint8_t *raw, uint64_t diroff,
-				      uint16_t ndirents, const char *name,
-				      uint16_t mode, const struct noid *child)
-{
-	uint8_t rawbuf[DIR_BLOCK_SIZE];
-	struct dirblock block;
-	struct buffer buffer;
-	ssize_t ret;
-
-	/* parse the block */
-	ret = dirblock_parse(&block, raw, ndirents);
-	if (ret)
-		return ret;
-
-	/* update the dirent target */
-	ret = __dir_create_update_dirent_real(&block, name, mode, child);
-	if (ret)
-		return ret;
-
-	/* serialize the block & write it out */
-	buffer_init_static(&buffer, rawbuf, 0, sizeof(rawbuf), true);
-
-	ret = dirblock_serialize(&block, &buffer);
-	if (ret)
-		return ret;
-
-	ret = obj_write(txn, dirver, buffer_data(&buffer), buffer_size(&buffer),
-			diroff);
-	if (ret < 0)
-		return ret;
-
-	if (ret != buffer_size(&buffer))
-		panic("dir block partial write!");
-
-	return 0;
-}
-
 int dir_create(struct txn *txn, struct objver *dirver, const char *name,
 	       uint32_t owner, uint32_t group, uint16_t mode,
 	       struct noid *_child)
@@ -248,14 +101,12 @@
 
 	/* add dirent to parent dir */
 	if (!update_existing) {
-		ret = __dir_create_add_dirent(txn, dirver, name, mode,
-					      &child->obj->oid);
+		ret = dir_add_dirent(txn, dirver, name, mode, &child->obj->oid);
 		if (ret)
 			goto err;
 	} else {
-		ret = __dir_create_update_dirent(txn, dirver, raw, diroff,
-						 ndirents, name, mode,
-						 &child->obj->oid);
+		ret = dir_update_dirent(txn, dirver, raw, diroff, ndirents,
+					name, mode, &child->obj->oid);
 		if (ret)
 			goto err;
 	}