From 0d81417e390541fcc8aaf8be2e034afa7c7ce84f Mon Sep 17 00:00:00 2001 From: ZeyadYasser Date: Thu, 16 Apr 2020 15:58:18 +0200 Subject: [PATCH] criu: optimize find_unix_sk_by_ino() Fixes: #339 Replaced the linear search with a hashtable lookup. Signed-off-by: Zeyad Yasser --- criu/files.c | 1 + criu/include/sockets.h | 2 ++ criu/sk-unix.c | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/criu/files.c b/criu/files.c index a1fd26764..2cfc9040e 100644 --- a/criu/files.c +++ b/criu/files.c @@ -1749,5 +1749,6 @@ struct collect_image_info files_cinfo = { int prepare_files(void) { init_fdesc_hash(); + init_sk_info_hash(); return collect_image(&files_cinfo); } diff --git a/criu/include/sockets.h b/criu/include/sockets.h index cd98d18e0..e971f3efd 100644 --- a/criu/include/sockets.h +++ b/criu/include/sockets.h @@ -62,6 +62,8 @@ extern int unix_sk_id_add(unsigned int ino); extern int unix_sk_ids_parse(char *optarg); extern int unix_prepare_root_shared(void); +extern void init_sk_info_hash(void); + extern int do_dump_opt(int sk, int level, int name, void *val, int len); #define dump_opt(s, l, n, f) do_dump_opt(s, l, n, f, sizeof(*f)) extern int do_restore_opt(int sk, int level, int name, void *val, int len); diff --git a/criu/sk-unix.c b/criu/sk-unix.c index 048ff44ae..cbcf1f66c 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -903,6 +903,7 @@ struct unix_sk_info { struct unix_sk_info *peer; struct pprep_head peer_resolve; /* XXX : union with the above? */ struct file_desc d; + struct hlist_node hash; /* To lookup socket by ino */ struct list_head connected; /* List of sockets, connected to me */ struct list_head node; /* To link in peer's connected list */ struct list_head scm_fles; @@ -934,11 +935,25 @@ struct scm_fle { #define USK_PAIR_SLAVE 0x2 #define USK_GHOST_FDSTORE 0x4 /* bound but removed address */ +#define SK_INFO_HASH_SIZE 32 + +static struct hlist_head sk_info_hash[SK_INFO_HASH_SIZE]; + +void init_sk_info_hash(void) +{ + int i; + + for (i = 0; i < SK_INFO_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sk_info_hash[i]); +} + static struct unix_sk_info *find_unix_sk_by_ino(int ino) { struct unix_sk_info *ui; + struct hlist_head *chain; - list_for_each_entry(ui, &unix_sockets, list) { + chain = &sk_info_hash[ino % SK_INFO_HASH_SIZE]; + hlist_for_each_entry(ui, chain, hash) { if (ui->ue->ino == ino) return ui; } @@ -2044,6 +2059,7 @@ static int init_unix_sk_info(struct unix_sk_info *ui, UnixSkEntry *ue) INIT_LIST_HEAD(&ui->node); INIT_LIST_HEAD(&ui->scm_fles); INIT_LIST_HEAD(&ui->ghost_node); + INIT_HLIST_NODE(&ui->hash); return 0; } @@ -2135,6 +2151,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i) list_add_tail(&ui->ghost_node, &unix_ghost_addr); } + hlist_add_head(&ui->hash, &sk_info_hash[ui->ue->ino % SK_INFO_HASH_SIZE]); list_add_tail(&ui->list, &unix_sockets); return file_desc_add(&ui->d, ui->ue->id, &unix_desc_ops); }