[CRIU] [PATCH 28/28] rst: replace binary tree for files with hash
table
Kinsbursky Stanislav
skinsbursky at openvz.org
Thu Mar 22 14:00:39 EDT 2012
From: Stanislav Kinsbursky <skinsbursky at openvz.org>
Signed-off-by: Stanislav Kinsbursky <skinsbursky at openvz.org>
---
file-ids.c | 78 +---------------------------------------------------
files.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/file-ids.h | 11 -------
include/files.h | 12 ++++++++
4 files changed, 88 insertions(+), 88 deletions(-)
-------------- next part --------------
diff --git a/file-ids.c b/file-ids.c
index 0ba9797..e155931 100644
--- a/file-ids.c
+++ b/file-ids.c
@@ -16,6 +16,7 @@
#include "compiler.h"
#include "syscall.h"
#include "util.h"
+#include "files.h"
/*
* We track shared files by global rbtree, where each node might
@@ -76,8 +77,6 @@ struct file_node {
static struct rb_root dump_file_forest[FD_INFO_MAX];
-static struct rb_root *restore_file_forest;
-
static int compare_map_files(pid_t pid1, pid_t pid2, u8 fd1, u8 fd2)
{
return 0;
@@ -200,78 +199,3 @@ long file_collect(pid_t pid, int fd, const struct file_entry *p, u8 *new_entry)
return e->u.id;
}
-static struct file_node *file_search_tree(struct rb_root *root, u64 id)
-{
- struct rb_node *node = root->rb_node;
-
- while (node) {
- struct file_node *this = rb_entry(node, struct file_node, node);
-
- if (id < this->u.id)
- node = node->rb_left;
- else if (id > this->u.id)
- node = node->rb_right;
- else
- return this;
- }
- return NULL;
-}
-
-struct file_info *file_search(u8 type, u64 id)
-{
- struct file_node *node;
-
- BUG_ON(restore_file_forest == NULL);
- node = file_search_tree(&restore_file_forest[type], id);
- if (node)
- return &node->info;
- return NULL;
-}
-
-int file_add(const struct file_entry *rfe)
-{
- struct rb_node *node;
- struct rb_node **new;
- struct rb_node *parent = NULL;
- struct rb_root *fd_root;
- struct file_node *e;
-
- if (rfe->type >= FD_INFO_MAX)
- return -ENOTSUP;
-
- if (restore_file_forest == NULL) {
- restore_file_forest = xmalloc_shm(sizeof(struct rb_root) * FD_INFO_MAX);
- if (restore_file_forest == NULL)
- return -ENOMEM;
- }
-
- fd_root = &restore_file_forest[rfe->type];
- node = fd_root->rb_node;
- new = &fd_root->rb_node;
-
- while (node) {
- struct file_node *this = rb_entry(node, struct file_node, node);
-
- parent = *new;
- if (rfe->id < this->u.id)
- node = node->rb_left, new = &((*new)->rb_left);
- else if (rfe->id > this->u.id)
- node = node->rb_right, new = &((*new)->rb_right);
- else
- return -EEXIST;
- }
-
- e = xmalloc_shm(sizeof(*e));
- if (!e)
- return -ENOMEM;
-
- e->u.id = rfe->id;
- e->info.rfe = rfe;
- e->info.fd = FD_ID_INVALID;
- e->info.pid = 0;
- INIT_LIST_HEAD(&e->info.recipients);
-
- rb_init_node(&e->node);
- rb_link_and_balance(fd_root, &e->node, parent, new);
- return 0;
-}
diff --git a/files.c b/files.c
index 2d882cf..f1434b8 100644
--- a/files.c
+++ b/files.c
@@ -20,6 +20,81 @@
#include "util-net.h"
#include "lock.h"
#include "file-ids.h"
+#include "image.h"
+
+#define HASH_TABLE_SIZE 32
+
+struct file_hash_entry {
+ struct list_head list;
+ u64 id;
+ struct file_info info;
+};
+
+struct files_hash {
+ struct list_head lists[HASH_TABLE_SIZE];
+};
+
+struct files_hash *files_hash_array;
+
+struct file_info *file_search(u8 type, u64 id)
+{
+ struct files_hash *hash;
+ struct list_head *hash_list;
+ struct file_hash_entry *e;
+
+ if (type >= FD_INFO_MAX)
+ return NULL;
+
+ hash = &files_hash_array[type];
+ hash_list = &hash->lists[id & (HASH_TABLE_SIZE - 1)];
+
+ list_for_each_entry(e, hash_list, list) {
+ if (e->id == id)
+ return &e->info;
+ }
+ return NULL;
+}
+
+static int file_add(const struct file_entry *rfe)
+{
+ struct files_hash *hash;
+ struct list_head *hash_list;
+ struct file_hash_entry *e;
+
+ if (rfe->type >= FD_INFO_MAX)
+ return -ENOTSUP;
+
+ if (files_hash_array == NULL) {
+ int i, j;
+
+ files_hash_array = xmalloc_shm(sizeof(struct files_hash) * FD_INFO_MAX);
+ if (files_hash_array == NULL)
+ return -ENOMEM;
+ for (i = 0; i < FD_INFO_MAX; i++) {
+ hash = &files_hash_array[i];
+ for (j = 0; j < HASH_TABLE_SIZE; j++)
+ INIT_LIST_HEAD(&hash->lists[j]);
+ }
+ }
+
+ if (file_search(rfe->type, rfe->id))
+ return -EEXIST;
+
+ e = xmalloc_shm(sizeof(*e));
+ if (!e)
+ return -ENOMEM;
+
+ e->id = rfe->id;
+ e->info.rfe = rfe;
+ e->info.fd = FD_ID_INVALID;
+ e->info.pid = 0;
+ INIT_LIST_HEAD(&e->info.recipients);
+
+ hash = &files_hash_array[rfe->type];
+ hash_list = &hash->lists[rfe->id & (HASH_TABLE_SIZE - 1)];
+ list_add_tail(&e->list, hash_list);
+ return 0;
+}
struct file_recipient {
struct list_head list;
diff --git a/include/file-ids.h b/include/file-ids.h
index c9d49be..25b1e82 100644
--- a/include/file-ids.h
+++ b/include/file-ids.h
@@ -5,7 +5,6 @@
#include "types.h"
#include "rbtree.h"
#include "image.h"
-#include "list.h"
#define FD_ID_INVALID (-1U)
#define FD_PID_INVALID ((int)-2UL)
@@ -13,16 +12,6 @@
#define MAKE_FD_GENID(dev, ino, pos) \
(((u32)(dev) ^ (u32)(ino) ^ (u32)(pos)))
-struct file_info {
- int fd;
- int pid;
- const struct file_entry *rfe;
- struct list_head recipients;
-};
-
extern long file_collect(pid_t pid, int fd, const struct file_entry *p, u8 *new_entry);
-extern struct file_info *file_search(u8 type, u64 id);
-extern int file_add(const struct file_entry *rfe);
-
#endif /* FILE_IDS_H__ */
diff --git a/include/files.h b/include/files.h
index 1bfa020..9eef25c 100644
--- a/include/files.h
+++ b/include/files.h
@@ -5,6 +5,7 @@
#include "types.h"
#include "list.h"
#include "image.h"
+#include "list.h"
enum fdinfo_states {
FD_STATE_PREP, /* Create unix sockets */
@@ -43,4 +44,15 @@ extern int prepare_fd_pid(int pid);
extern int prepare_files(void);
extern int get_filemap_fd(int pid, struct vma_entry *vma_entry);
+struct file_entry;
+
+struct file_info {
+ int fd;
+ int pid;
+ const struct file_entry *rfe;
+ struct list_head recipients;
+};
+
+extern struct file_info *file_search(u8 type, u64 id);
+
#endif /* FILES_H_ */
More information about the CRIU
mailing list