changeset 639:d57bc9242936

client: implement an inode number mapping layer Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Fri, 15 Feb 2019 07:58:15 -0500
parents 0df06bfe7165
children 3e4666a456de
files src/client/CMakeLists.txt src/client/cmds.h src/client/inode_map.c src/client/inode_map.h src/client/main.c
diffstat 5 files changed, 209 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/client/CMakeLists.txt	Thu Feb 21 18:54:05 2019 -0500
+++ b/src/client/CMakeLists.txt	Fri Feb 15 07:58:15 2019 -0500
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+# Copyright (c) 2015-2019 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
@@ -23,6 +23,7 @@
 add_executable(nomad-client
 	main.c
 	cmds.c
+	inode_map.c
 	ohandle.c
 
 	# assorted RPC handlers
--- a/src/client/cmds.h	Thu Feb 21 18:54:05 2019 -0500
+++ b/src/client/cmds.h	Fri Feb 15 07:58:15 2019 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright (c) 2015-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  * Copyright (c) 2015 Holly Sipek
  * Copyright (c) 2016 Steve Dougherty
  *
@@ -30,6 +30,8 @@
 #include <nomad/rpc_fs.h>
 #include <nomad/objstore.h>
 
+#include "inode_map.h"
+
 union cmd {
 	/* close */
 	struct {
@@ -125,6 +127,7 @@
 	struct objstore *vol;
 
 	struct rb_tree open_handles;
+	struct inode_map inode_map;
 };
 
 extern bool process_handshake(struct fsconn *conn);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/client/inode_map.c	Fri Feb 15 07:58:15 2019 -0500
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019 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 <jeffpc/mem.h>
+#include <jeffpc/error.h>
+
+#include "inode_map.h"
+
+struct inode_map_entry {
+	struct rb_node fwd;
+	struct rb_node rev;
+	struct noid oid;
+	uint64_t ino;
+};
+
+static struct mem_cache *inode_map_entry_cache;
+
+int inode_map_init(void)
+{
+	inode_map_entry_cache = mem_cache_create("inode-map-entry",
+						 sizeof(struct inode_map_entry),
+						 0);
+	if (IS_ERR(inode_map_entry_cache))
+		return PTR_ERR(inode_map_entry_cache);
+
+	return 0;
+}
+
+static int inode_map_entry_cmp_oid(const void *va, const void *vb)
+{
+	const struct inode_map_entry *a = va;
+	const struct inode_map_entry *b = vb;
+
+	return noid_cmp(&a->oid, &b->oid);
+}
+
+static int inode_map_entry_cmp_ino(const void *va, const void *vb)
+{
+	const struct inode_map_entry *a = va;
+	const struct inode_map_entry *b = vb;
+
+	if (a->ino < b->ino)
+		return -1;
+	if (a->ino > b->ino)
+		return 1;
+	return 0;
+}
+
+void inode_map_alloc(struct inode_map *map)
+{
+	rb_create(&map->fwd, inode_map_entry_cmp_oid,
+		  sizeof(struct inode_map_entry),
+		  offsetof(struct inode_map_entry, fwd));
+	rb_create(&map->rev, inode_map_entry_cmp_ino,
+		  sizeof(struct inode_map_entry),
+		  offsetof(struct inode_map_entry, rev));
+
+	map->next_ino = 1; /* the first inode number to use */
+}
+
+void inode_map_free(struct inode_map *map)
+{
+	struct inode_map_entry *entry;
+	struct rb_cookie cookie;
+
+	memset(&cookie, 0, sizeof(struct rb_cookie));
+	while ((entry = rb_destroy_nodes(&map->rev, &cookie)))
+		; /* nothing to do */
+
+	memset(&cookie, 0, sizeof(struct rb_cookie));
+	while ((entry = rb_destroy_nodes(&map->fwd, &cookie)))
+		mem_cache_free(inode_map_entry_cache, entry);
+
+	rb_destroy(&map->fwd);
+	rb_destroy(&map->rev);
+}
+
+int inode_map_find_by_oid(struct inode_map *map, const struct noid *oid,
+			  uint64_t *ino_r)
+{
+	const struct inode_map_entry key = {
+		.oid = *oid,
+	};
+	struct inode_map_entry *entry;
+	struct rb_cookie where;
+
+	/* check if we already have a oid -> ino mapped */
+	entry = rb_find(&map->fwd, &key, &where);
+	if (entry) {
+		*ino_r = entry->ino;
+		return 0;
+	}
+
+	entry = mem_cache_alloc(inode_map_entry_cache);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->oid = *oid;
+	entry->ino = map->next_ino++;
+
+	rb_insert_here(&map->fwd, entry, &where);
+	rb_add(&map->rev, entry);
+
+	*ino_r = entry->ino;
+
+	return 0;
+}
+
+int inode_map_find_by_ino(struct inode_map *map, uint64_t ino,
+			  struct noid *oid_r)
+{
+	const struct inode_map_entry key = {
+		.ino = ino,
+	};
+	struct inode_map_entry *entry;
+
+	entry = rb_find(&map->rev, &key, NULL);
+	if (!entry)
+		return -ENOENT;
+
+	*oid_r = entry->oid;
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/client/inode_map.h	Fri Feb 15 07:58:15 2019 -0500
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#ifndef __NOMAD_CLIENT_INODE_MAP_H
+#define __NOMAD_CLIENT_INODE_MAP_H
+
+#include <jeffpc/rbtree.h>
+
+#include <nomad/types.h>
+
+struct inode_map {
+	struct rb_tree fwd; /* oid -> ino */
+	struct rb_tree rev; /* ino -> oid */
+
+	uint64_t next_ino; /* next inode number to allocate */
+};
+
+extern int inode_map_init(void);
+extern void inode_map_alloc(struct inode_map *map);
+extern void inode_map_free(struct inode_map *map);
+
+/* look up ino by oid; allocates & returns a new ino if not found */
+extern int inode_map_find_by_oid(struct inode_map *map, const struct noid *oid,
+				 uint64_t *ino_r);
+/* look up oid by ino; returns -ENOENT if not found */
+extern int inode_map_find_by_ino(struct inode_map *map, uint64_t ino,
+				 struct noid *oid_r);
+
+#endif
--- a/src/client/main.c	Thu Feb 21 18:54:05 2019 -0500
+++ b/src/client/main.c	Fri Feb 15 07:58:15 2019 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright (c) 2015-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  * Copyright (c) 2015 Holly Sipek
  * Copyright (c) 2016 Steve Dougherty
  *
@@ -46,6 +46,8 @@
 	conn.fd = fd;
 	conn.vol = NULL;
 
+	inode_map_alloc(&conn.inode_map);
+
 	rb_create(&conn.open_handles, ohandle_cmp, sizeof(struct ohandle),
 		  offsetof(struct ohandle, node));
 
@@ -57,6 +59,8 @@
 
 	ohandle_close_all(&conn);
 
+	inode_map_free(&conn.inode_map);
+
 	rb_destroy(&conn.open_handles);
 }
 
@@ -64,6 +68,13 @@
 {
 	int ret;
 
+	ret = inode_map_init();
+	if (ret) {
+		cmn_err(CE_CRIT, "failed to initialize inode-map subsystem: %s",
+			xstrerror(ret));
+		goto err;
+	}
+
 	ret = ohandle_init();
 	if (ret) {
 		cmn_err(CE_CRIT, "failed to initialize ohandle subsystem: %s",