[CRIU] [PATCH 4/4] files: Cache special file IDs

Pavel Emelyanov xemul at parallels.com
Tue Feb 4 08:03:46 PST 2014


We have tons of files with equal IDs, e.g. libraries mapped
to different tasks. We can avoid writing all this duplicate 
stuff into images by caching the IDs with dev:ino keys.

This looks _very_ similar to irmap cache, but the latter one
caches dev:ino into paths. Need to think how to merge them.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 file-ids.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 63 insertions(+), 1 deletion(-)

diff --git a/file-ids.c b/file-ids.c
index 7cac60f..30f1bbc 100644
--- a/file-ids.c
+++ b/file-ids.c
@@ -6,7 +6,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
-
+#include <sys/stat.h>
 #include <sys/types.h>
 
 #include "asm/types.h"
@@ -26,9 +26,68 @@ void fd_id_show_tree(void)
 	kid_show_tree(&fd_tree);
 }
 
+#define FDID_BITS	5
+#define FDID_SIZE	(1 << FDID_BITS)
+#define FDID_MASK	(FDID_SIZE - 1)
+
+static inline int fdid_hashfn(unsigned int s_dev, unsigned long i_ino)
+{
+	return (s_dev + i_ino) & FDID_MASK;
+}
+
+struct fd_id {
+	unsigned int dev;
+	unsigned long ino;
+	u32 id;
+	struct fd_id *n;
+};
+
+static struct fd_id *fd_id_cache[FDID_SIZE];
+
+static void fd_id_cache_one(u32 id, struct stat *st)
+{
+	struct fd_id *fi;
+	unsigned hv;
+
+	fi = xmalloc(sizeof(*fi));
+	if (fi) {
+		fi->dev = st->st_dev;
+		fi->ino = st->st_ino;
+		fi->id = id;
+
+		hv = fdid_hashfn(st->st_dev, st->st_ino);
+		fi->n = fd_id_cache[hv];
+		fd_id_cache[hv] = fi;
+	}
+}
+
+static struct fd_id *fd_id_cache_lookup(struct stat *st)
+{
+	struct fd_id *fi;
+
+	for (fi = fd_id_cache[fdid_hashfn(st->st_dev, st->st_ino)];
+			fi; fi = fi->n)
+		if (fi->dev == st->st_dev && fi->ino == st->st_ino)
+			return fi;
+
+	return NULL;
+}
+
 int fd_id_generate_special(struct stat *st, u32 *id)
 {
+	if (st) {
+		struct fd_id *fi;
+
+		fi = fd_id_cache_lookup(st);
+		if (fi) {
+			*id = fi->id;
+			return 0;
+		}
+	}
+
 	*id = fd_tree.subid++;
+	if (st)
+		fd_id_cache_one(*id, st);
 	return 1;
 }
 
@@ -46,6 +105,9 @@ int fd_id_generate(pid_t pid, FdinfoEntry *fe, struct stat *st)
 	if (!id)
 		return -ENOMEM;
 
+	if (new_id)
+		fd_id_cache_one(id, st);
+
 	fe->id = id;
 	return new_id;
 }
-- 
1.8.4.2


More information about the CRIU mailing list