diff mbox series

[2/2] Remove undocumented and unmaintained tools/memshr library

Message ID 20200110023052.21159-2-tamas@tklengyel.com (mailing list archive)
State New, archived
Headers show
Series [1/2] MAINTAINERS: adjust path of actually maintained memshr code in tools | expand

Commit Message

Tamas K Lengyel Jan. 10, 2020, 2:30 a.m. UTC
The library has been largely untouched for over a decade at this point, it is
undocumented and it's unclear what it was originally used for. Remove it from
tree, if anyone needs it in the future it can be carved out from git history.

Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
---
 tools/Makefile                |    1 -
 tools/memshr/Makefile         |   49 --
 tools/memshr/bidir-daemon.c   |  103 ---
 tools/memshr/bidir-daemon.h   |   24 -
 tools/memshr/bidir-hash.c     | 1355 ---------------------------------
 tools/memshr/bidir-hash.h     |  114 ---
 tools/memshr/bidir-namedefs.h |   79 --
 tools/memshr/interface.c      |  224 ------
 tools/memshr/memshr-priv.h    |   33 -
 tools/memshr/memshr.h         |   51 --
 tools/memshr/shm.c            |  262 -------
 tools/memshr/shm.h            |   49 --
 12 files changed, 2344 deletions(-)
 delete mode 100644 tools/memshr/Makefile
 delete mode 100644 tools/memshr/bidir-daemon.c
 delete mode 100644 tools/memshr/bidir-daemon.h
 delete mode 100644 tools/memshr/bidir-hash.c
 delete mode 100644 tools/memshr/bidir-hash.h
 delete mode 100644 tools/memshr/bidir-namedefs.h
 delete mode 100644 tools/memshr/interface.c
 delete mode 100644 tools/memshr/memshr-priv.h
 delete mode 100644 tools/memshr/memshr.h
 delete mode 100644 tools/memshr/shm.c
 delete mode 100644 tools/memshr/shm.h

Comments

Andrew Cooper Jan. 10, 2020, 5:59 p.m. UTC | #1
On 10/01/2020 02:30, Tamas K Lengyel wrote:
> The library has been largely untouched for over a decade at this point, it is
> undocumented and it's unclear what it was originally used for. Remove it from
> tree, if anyone needs it in the future it can be carved out from git history.
>
> Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>

Hmm - this is a little awkward.  You remove yourself as maintainer of
this code, then delete it.

I suspect what you want to do is have patch 1 simply add tools/test
saying "include other memshr content", and this patch delete
tools/memshr including the entry in the maintainers file.  (Can be fixed
up on commit of course, seeing as this is the only issue.)

Overall, I agree with the change, but it will need a tools ack.

~Andrew
Tamas K Lengyel Jan. 10, 2020, 6:40 p.m. UTC | #2
On Fri, Jan 10, 2020 at 10:59 AM Andrew Cooper
<andrew.cooper3@citrix.com> wrote:
>
> On 10/01/2020 02:30, Tamas K Lengyel wrote:
> > The library has been largely untouched for over a decade at this point, it is
> > undocumented and it's unclear what it was originally used for. Remove it from
> > tree, if anyone needs it in the future it can be carved out from git history.
> >
> > Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
>
> Hmm - this is a little awkward.  You remove yourself as maintainer of
> this code, then delete it.
>
> I suspect what you want to do is have patch 1 simply add tools/test
> saying "include other memshr content", and this patch delete
> tools/memshr including the entry in the maintainers file.  (Can be fixed
> up on commit of course, seeing as this is the only issue.)
>
> Overall, I agree with the change, but it will need a tools ack.
>

I was considering just squashing the two patches into one but wasn't
sure if anyone would object to removing dead code (that seems to be
never done). So if there is no objection and the only problem is
"ordering", it would be simpler to just squash the two into one during
commit.

Tamas
Wei Liu Jan. 14, 2020, 11:48 a.m. UTC | #3
On Fri, Jan 10, 2020 at 05:59:44PM +0000, Andrew Cooper wrote:
> On 10/01/2020 02:30, Tamas K Lengyel wrote:
> > The library has been largely untouched for over a decade at this point, it is
> > undocumented and it's unclear what it was originally used for. Remove it from
> > tree, if anyone needs it in the future it can be carved out from git history.
> >
> > Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
> 
> Hmm - this is a little awkward.  You remove yourself as maintainer of
> this code, then delete it.
> 
> I suspect what you want to do is have patch 1 simply add tools/test
> saying "include other memshr content", and this patch delete
> tools/memshr including the entry in the maintainers file.  (Can be fixed
> up on commit of course, seeing as this is the only issue.)
> 
> Overall, I agree with the change, but it will need a tools ack.
> 

I mostly agree with Tamas' assessment. No point in keeping dead and
unused code in tree.

Acked-by: Wei Liu <wl@xen.org>

Wei.

> ~Andrew
Andrew Cooper Jan. 14, 2020, noon UTC | #4
On 14/01/2020 11:48, Wei Liu wrote:
> On Fri, Jan 10, 2020 at 05:59:44PM +0000, Andrew Cooper wrote:
>> On 10/01/2020 02:30, Tamas K Lengyel wrote:
>>> The library has been largely untouched for over a decade at this point, it is
>>> undocumented and it's unclear what it was originally used for. Remove it from
>>> tree, if anyone needs it in the future it can be carved out from git history.
>>>
>>> Signed-off-by: Tamas K Lengyel <tamas@tklengyel.com>
>> Hmm - this is a little awkward.  You remove yourself as maintainer of
>> this code, then delete it.
>>
>> I suspect what you want to do is have patch 1 simply add tools/test
>> saying "include other memshr content", and this patch delete
>> tools/memshr including the entry in the maintainers file.  (Can be fixed
>> up on commit of course, seeing as this is the only issue.)
>>
>> Overall, I agree with the change, but it will need a tools ack.
>>
> I mostly agree with Tamas' assessment. No point in keeping dead and
> unused code in tree.
>
> Acked-by: Wei Liu <wl@xen.org>

Cool.  If noone else gets to it, I'll see about committing this series
and shuffling the order of operations.

~Andrew
diff mbox series

Patch

diff --git a/tools/Makefile b/tools/Makefile
index 7b1f6c4d28..c10946e3b1 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,7 +19,6 @@  SUBDIRS-$(CONFIG_X86) += firmware
 SUBDIRS-y += console
 SUBDIRS-y += xenmon
 SUBDIRS-y += xenstat
-SUBDIRS-$(CONFIG_Linux) += memshr 
 SUBDIRS-$(CONFIG_NetBSD) += xenbackendd
 SUBDIRS-y += libfsimage
 SUBDIRS-$(CONFIG_Linux) += libvchan
diff --git a/tools/memshr/Makefile b/tools/memshr/Makefile
deleted file mode 100644
index 31d2dd7ada..0000000000
--- a/tools/memshr/Makefile
+++ /dev/null
@@ -1,49 +0,0 @@ 
-XEN_ROOT = $(CURDIR)/../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-LIBMEMSHR-BUILD := libmemshr.a
-
-CFLAGS          += -Werror
-CFLAGS          += -Wno-unused
-CFLAGS          += $(CFLAGS_xeninclude)
-CFLAGS          += $(CFLAGS_libxenctrl)
-CFLAGS          += -D_GNU_SOURCE
-CFLAGS          += -fPIC
-
-LIB-SRCS        := interface.c
-LIB-SRCS        += shm.c
-LIB-SRCS        += bidir-daemon.c
-LIB-SRCS        += bidir-hash.c
-
-LIB-OBJS        := interface.o
-LIB-OBJS        += shm.o
-LIB-OBJS        += bidir-daemon.o
-LIB-OBJS        += bidir-hash-fgprtshr.o
-LIB-OBJS        += bidir-hash-blockshr.o
-
-all: build
-
-build: $(LIBMEMSHR-BUILD)
-
-bidir-hash-fgprtshr.o: bidir-hash.c
-	$(CC) $(CFLAGS) -DFINGERPRINT_MAP -c -o $*.o bidir-hash.c 
-
-bidir-hash-blockshr.o: bidir-hash.c
-	$(CC) $(CFLAGS) -DBLOCK_MAP -c -o $*.o bidir-hash.c 
-
-libmemshr.a: $(LIB-OBJS)
-	$(AR) rc $@ $^
-
-install: all
-
-uninstall:
-
-clean:
-	rm -rf *.a *.o *~ $(DEPS_RM)
-
-.PHONY: distclean
-distclean: clean
-
-.PHONY: all build clean install distclean uninstall
-
--include $(DEPS_INCLUDE)
diff --git a/tools/memshr/bidir-daemon.c b/tools/memshr/bidir-daemon.c
deleted file mode 100644
index ddb7c00319..0000000000
--- a/tools/memshr/bidir-daemon.c
+++ /dev/null
@@ -1,103 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#include <pthread.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "bidir-hash.h"
-#include "memshr-priv.h"
-
-static struct blockshr_hash *blks_hash;
-
-/* Callback in the iterator, remember this value, and leave */
-int find_one(vbdblk_t k, share_tuple_t v, void *priv)
-{
-    share_tuple_t *rv = (share_tuple_t *) priv;
-    *rv = v;
-    /* Break out of iterator loop */
-    return 1;
-}
-
-void* bidir_daemon(void *unused)
-{
-    uint32_t nr_ent, max_nr_ent, tab_size, max_load, min_load;
-
-    while(1)
-    {
-        blockshr_hash_sizes( blks_hash, 
-                            &nr_ent, 
-                            &max_nr_ent,
-                            &tab_size, 
-                            &max_load, 
-                            &min_load);
-        /* Remove some hints as soon as we get to 90% capacity */ 
-        if(10 * nr_ent > 9 * max_nr_ent)
-        {
-            share_tuple_t next_remove;
-            int to_remove;
-            int ret;
-
-            to_remove = 0.1 * max_nr_ent; 
-            while(to_remove > 0) 
-            {
-                /* We use the iterator to get one entry */
-                next_remove.handle = 0;
-                ret = blockshr_hash_iterator(blks_hash, find_one, &next_remove);
-
-                if ( !ret )
-                    if ( next_remove.handle == 0 )
-                        ret = -ESRCH;
-
-                if ( !ret )
-                    ret = blockshr_shrhnd_remove(blks_hash, next_remove, NULL);
-
-                if(ret <= 0)
-                {
-                    /* We failed to remove an entry, because of a serious hash
-                     * table error */
-                    DPRINTF("Could not remove handle %"PRId64", error: %d\n",
-                            next_remove.handle, ret);
-                    /* Force to exit the loop early */
-                    to_remove = 0;
-                } else 
-                if(ret > 0)
-                {
-                    /* Managed to remove the entry. Note next_remove not
-                     * incremented, in case there are duplicates */
-                    to_remove--;
-                }
-            }
-        }
-
-        sleep(1);
-    }
-}
-
-void bidir_daemon_launch(void)
-{
-    pthread_t thread; 
-
-    pthread_create(&thread, NULL, bidir_daemon, NULL);
-}
-
-void bidir_daemon_initialize(struct blockshr_hash *blks)
-{
-    blks_hash = blks; 
-    bidir_daemon_launch();
-}
diff --git a/tools/memshr/bidir-daemon.h b/tools/memshr/bidir-daemon.h
deleted file mode 100644
index f683280678..0000000000
--- a/tools/memshr/bidir-daemon.h
+++ /dev/null
@@ -1,24 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __BIDIR_DAEMON_H__
-#define __BIDIR_DAEMON_H__
-
-void bidir_daemon_initialize(struct blockshr_hash *blks);
-
-#endif /* __BIDIR_DAEMON_H__ */
diff --git a/tools/memshr/bidir-hash.c b/tools/memshr/bidir-hash.c
deleted file mode 100644
index c5cc71e3ca..0000000000
--- a/tools/memshr/bidir-hash.c
+++ /dev/null
@@ -1,1355 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#include <assert.h>
-#include <errno.h>
-#include <math.h>
-#include <pthread.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "bidir-hash.h"
-
-static const uint32_t hash_sizes[] = {53, 97, 193, 389, 769, 1543, 3079, 6151,
-    12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739,
-    6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
-    805306457, 1610612741};
-static const uint16_t hash_sizes_len =
-            sizeof(hash_sizes)/sizeof(hash_sizes[0]);
-static const float hash_max_load_fact = 0.65;
-static const float hash_min_load_fact = 0.10;
-
-/* How many buckets will be covered by a single rw lock */
-#define BUCKETS_PER_LOCK    64
-#define nr_locks(_nr_buckets)   (1 + (_nr_buckets) / BUCKETS_PER_LOCK)
-
-
-#define HASH_LOCK                                                              \
-    pthread_rwlock_t hash_lock
-
-#define BUCKET_LOCK                                                            \
-    pthread_rwlock_t bucket_lock
-
-struct hash_entry
-{
-    __k_t key;
-    __v_t value;
-    /* This structure will belong to two buckets, one in each hash table */
-    struct hash_entry *key_next;
-    struct hash_entry *value_next;
-};
-
-struct bucket
-{
-    struct hash_entry *hash_entry;
-};
-
-struct bucket_lock
-{
-    BUCKET_LOCK;
-};
-
-struct __hash
-{
-    int lock_alive;
-    HASH_LOCK;                            /* protects:
-                                           * *_tab, tab_size, size_idx, *_load
-                                           * (all writes with wrlock)
-                                           */
-    uint32_t nr_ent;                      /* # entries held in hashtables */
-    struct bucket *key_tab;               /* forward mapping hashtable    */
-    struct bucket *value_tab;             /* backward mapping hashtable   */
-    struct bucket_lock *key_lock_tab;     /* key table bucket locks       */
-    struct bucket_lock *value_lock_tab;   /* value table bucket locks     */
-    uint32_t tab_size;                    /* # buckets is hashtables      */
-    uint16_t size_idx;                    /* table size index             */
-    uint32_t max_load;                    /* # entries before rehash      */
-    uint32_t min_load;                    /* # entries before rehash      */
-};
-
-struct __hash *__hash_init   (struct __hash *h, uint32_t min_size);
-int            __key_lookup  (struct __hash *h, __k_t k, __v_t *vp);
-int            __value_lookup(struct __hash *h, __v_t v, __k_t *kp);
-int            __insert      (struct __hash *h, __k_t k, __v_t v);
-int            __key_remove  (struct __hash *h, __k_t k, __v_t *vp);
-int            __value_remove(struct __hash *h, __v_t v, __k_t *kp);
-int            __hash_destroy(struct __hash *h,
-                    void (*entry_consumer)(__k_t k, __v_t v, void *p),
-                    void *d);
-int            __hash_iterator(struct __hash *h,
-                        int (*entry_consumer)(__k_t k, __v_t v, void *p),
-                        void *d);
-static void      hash_resize(struct __hash *h);
-
-#if defined(__arm__)
-static inline void atomic_inc(uint32_t *v)
-{
-        unsigned long tmp;
-        int result;
-
-        __asm__ __volatile__("@ atomic_inc\n"
-"1:     ldrex   %0, [%3]\n"
-"       add     %0, %0, #1\n"
-"       strex   %1, %0, [%3]\n"
-"       teq     %1, #0\n"
-"       bne     1b"
-        : "=&r" (result), "=&r" (tmp), "+Qo" (*v)
-        : "r" (v)
-        : "cc");
-}
-static inline void atomic_dec(uint32_t *v)
-{
-        unsigned long tmp;
-        int result;
-
-        __asm__ __volatile__("@ atomic_dec\n"
-"1:     ldrex   %0, [%3]\n"
-"       sub     %0, %0, #1\n"
-"       strex   %1, %0, [%3]\n"
-"       teq     %1, #0\n"
-"       bne     1b"
-        : "=&r" (result), "=&r" (tmp), "+Qo" (*v)
-        : "r" (v)
-        : "cc");
-}
-
-#elif defined(__aarch64__)
-
-static inline void atomic_inc(uint32_t *v)
-{
-        unsigned long tmp;
-        int result;
-
-        asm volatile("// atomic_inc\n"
-"1:     ldxr    %w0, [%3]\n"
-"       add     %w0, %w0, #1\n"
-"       stxr    %w1, %w0, [%3]\n"
-"       cbnz    %w1, 1b"
-        : "=&r" (result), "=&r" (tmp), "+o" (v)
-        : "r" (v)
-        : "cc");
-}
-
-static inline void atomic_dec(uint32_t *v)
-{
-        unsigned long tmp;
-        int result;
-
-        asm volatile("// atomic_dec\n"
-"1:     ldxr    %w0, [%3]\n"
-"       sub     %w0, %w0, #1\n"
-"       stxr    %w1, %w0, [%3]\n"
-"       cbnz    %w1, 1b"
-        : "=&r" (result), "=&r" (tmp), "+o" (v)
-        : "r" (v)
-        : "cc");
-}
-
-#else /* __x86__ */
-static inline void atomic_inc(uint32_t *v)
-{
-    asm volatile (
-        "lock ; incl %0"
-        : "=m" (*(volatile uint32_t *)v)
-        : "m" (*(volatile uint32_t *)v) );
-}
-static inline void atomic_dec(uint32_t *v)
-{
-    asm volatile (
-        "lock ; decl %0"
-        : "=m" (*(volatile uint32_t *)v)
-        : "m" (*(volatile uint32_t *)v) );
-}
-#endif
-
-#ifdef BIDIR_USE_STDMALLOC
-
-static void* alloc_entry(struct __hash *h, int size)
-{
-    return malloc(size);
-}
-
-static void alloc_buckets(struct __hash *h,
-                          int nr_buckets,
-                          struct bucket **bucket_tab,
-                          struct bucket_lock **bucket_locks_tab)
-{
-    *bucket_tab = (struct bucket*)
-        malloc(nr_buckets * sizeof(struct bucket));
-    *bucket_locks_tab = (struct bucket_lock*)
-        malloc(nr_locks(nr_buckets) * sizeof(struct bucket_lock));
-}
-
-static void free_entry(struct __hash *h, void *p)
-{
-    free(p);
-}
-
-static void free_buckets(struct __hash *h,
-                         struct bucket *buckets,
-                         struct bucket_lock *bucket_locks)
-{
-    free(buckets);
-    free(bucket_locks);
-}
-
-static int max_entries(struct __hash *h)
-{
-    /* There are no explicit restrictions to how many entries we can store */
-    return -1;
-}
-
-#else
-
-/*****************************************************************************/
-/** Memory allocator for shared memory region **/
-/*****************************************************************************/
-#define SHM_TABLE_SLOTS 4
-
-struct shm_hdr
-{
-    int             hash_allocated;
-    pthread_mutex_t mutex;
-    int             free_tab_slots[SHM_TABLE_SLOTS];
-
-    unsigned long   freelist_offset;
-                    
-    unsigned long   entries_offset;
-    unsigned long   nr_entries;
-                    
-    unsigned long   tabs_offset;
-    unsigned long   max_tab_size;
-    unsigned long   max_lock_tab_size;
-
-    struct __hash   hash;
-};
-
-static unsigned long get_shm_baddr(void *hdr)
-{
-    return ((unsigned long)hdr - offsetof(struct shm_hdr, hash));
-}
-
-
-/** Locations of various structures/memory areas **/
-static struct shm_hdr* get_shm_hdr(struct __hash *h)
-{
-    return (struct shm_hdr *)
-            ((unsigned long)h - offsetof(struct shm_hdr, hash));
-}
-
-static uint32_t* get_shm_freelist(struct shm_hdr *hdr)
-{
-    unsigned long shm_baddr = (unsigned long)hdr;
-    return ((uint32_t *)(shm_baddr + hdr->freelist_offset));
-}
-
-static struct hash_entry* get_shm_entries(struct shm_hdr *hdr)
-{
-    unsigned long shm_baddr = (unsigned long)hdr;
-    return ((struct hash_entry *)(shm_baddr + hdr->entries_offset));
-}
-
-static struct bucket* get_shm_tab(struct shm_hdr *hdr, int i)
-{
-    unsigned long shm_baddr = (unsigned long)hdr;
-    return ((struct bucket *)
-               ((shm_baddr + hdr->tabs_offset) +
-                 i * (hdr->max_tab_size + hdr->max_lock_tab_size)));
-}
-
-static struct bucket_lock* get_shm_lock_tab(struct shm_hdr *hdr, int i)
-{
-    unsigned long shm_baddr = (unsigned long)hdr;
-    return ((struct bucket_lock *)
-               ((shm_baddr + hdr->tabs_offset) +
-                 i * (hdr->max_tab_size + hdr->max_lock_tab_size) +
-                 hdr->max_tab_size));
-}
-
-static int get_shm_slot(struct shm_hdr *hdr, void *p)
-{
-    unsigned long shm_baddr = (unsigned long)hdr;
-    return ((unsigned long)p - (shm_baddr + hdr->tabs_offset)) /
-              (hdr->max_tab_size + hdr->max_lock_tab_size);
-}
-
-/* Shared memory allocator locks */
-static int shm_mutex_init(struct shm_hdr *h)
-{
-    int ret;
-    pthread_mutexattr_t _attr;
-
-    ret = pthread_mutexattr_init(&_attr);
-    if(ret == 0)
-        ret = pthread_mutexattr_setpshared(&_attr, PTHREAD_PROCESS_SHARED);
-    if(ret == 0)
-        ret = pthread_mutex_init(&h->mutex, &_attr);
-    if(ret == 0)
-        ret = pthread_mutexattr_destroy(&_attr);
-
-    return ret;
-};
-
-static int shm_mutex_lock(struct shm_hdr *h)
-{
-    return pthread_mutex_lock(&h->mutex);
-}
-
-static int shm_mutex_unlock(struct shm_hdr *h)
-{
-    return pthread_mutex_unlock(&h->mutex);
-}
-
-
-/* Shared memory allocator freelist */
-static void shm_add_to_freelist(struct shm_hdr *hdr, uint32_t sl)
-{
-    uint32_t *freelist = get_shm_freelist(hdr);
-
-    shm_mutex_lock(hdr);
-    freelist[sl+1] = freelist[0];
-    freelist[0] = sl;
-    shm_mutex_unlock(hdr);
-}
-
-static uint32_t shm_get_from_freelist(struct shm_hdr *hdr)
-{
-    uint32_t *freelist = get_shm_freelist(hdr);
-    uint32_t slot;
-
-    shm_mutex_lock(hdr);
-    slot = freelist[0];
-    freelist[0] = freelist[slot+1];
-    shm_mutex_unlock(hdr);
-
-    return (slot == 0 ? -1 : slot);
-}
-
-
-#define SHM_ALLOC_MAIN(_n)
-
-static unsigned long shm_init_offsets(
-                                    struct shm_hdr *hdr, int nr_entries)
-{
-    hdr->freelist_offset = sizeof(struct shm_hdr);
-
-    /* Freelist needs one extra slot in the array for the freelist head */
-    hdr->entries_offset =
-        hdr->freelist_offset + (nr_entries + 1) * sizeof(uint32_t);
-    hdr->nr_entries = nr_entries;
-
-    hdr->tabs_offset = hdr->entries_offset +
-        nr_entries * sizeof(struct hash_entry);
-    /* We want to allocate table 1.5 larger than the number of entries
-       we want to hold in it */
-    hdr->max_tab_size =
-        (nr_entries * 3 / 2) * sizeof(struct bucket);
-    hdr->max_lock_tab_size =
-        nr_locks(hdr->max_tab_size) * sizeof(struct bucket_lock);
-
-    return hdr->tabs_offset + (hdr->max_tab_size + hdr->max_lock_tab_size) * 4;
-}
-
-struct __hash* __shm_hash_init(unsigned long shm_baddr, unsigned long shm_size)
-{
-    uint32_t i;
-    struct shm_hdr *hdr;
-
-    /* Some sanity checks */
-    hdr = (struct shm_hdr *)shm_baddr;
-    memset(hdr, 0, sizeof(struct shm_hdr));
-
-    /* Find the maximum number of entries we can store in the given shm_size */
-    for(i=1; shm_init_offsets(hdr, i) < shm_size; i++){};
-    shm_init_offsets(hdr, (i-1));
-
-    memset(get_shm_freelist(hdr), 0,
-           (hdr->nr_entries + 1) * sizeof(uint32_t));
-    if(shm_mutex_init(hdr) != 0)
-        return NULL;
-    for(i=0; i<hdr->nr_entries; i++)
-        shm_add_to_freelist(hdr, i);
-    for(i=0; i<SHM_TABLE_SLOTS; i++)
-        hdr->free_tab_slots[i] = 1;
-
-    shm_mutex_lock(hdr);
-    assert(!hdr->hash_allocated);
-    hdr->hash_allocated = 1;
-    shm_mutex_unlock(hdr);
-
-    return __hash_init(&hdr->hash, 1000);
-}
-
-struct __hash* __shm_hash_get(unsigned long shm_baddr)
-{
-    struct shm_hdr *hdr = (struct shm_hdr *)shm_baddr;
-
-    return (hdr->hash_allocated ? &hdr->hash : NULL);
-}
-
-static void* alloc_entry(struct __hash *h, int size)
-{
-    struct shm_hdr *hdr = get_shm_hdr(h);
-    uint32_t slot = shm_get_from_freelist(hdr);
-
-    assert(size == sizeof(struct hash_entry));
-    if(slot == -1)
-        return NULL;
-
-    return (get_shm_entries(hdr) + slot);
-}
-
-static void alloc_buckets(struct __hash *h,
-                          int nr_buckets,
-                          struct bucket **buckets_tab,
-                          struct bucket_lock **bucket_locks_tab)
-{
-    struct shm_hdr *hdr = get_shm_hdr(h);
-    int free_slot;
-
-    *buckets_tab = NULL;
-    *bucket_locks_tab = NULL;
-
-    if(((nr_buckets * sizeof(struct bucket)) > hdr->max_tab_size) ||
-       ((nr_locks(nr_buckets) * sizeof(struct bucket_lock)) >
-                                                hdr->max_lock_tab_size))
-        return;
-
-    shm_mutex_lock(hdr);
-    for(free_slot=0; free_slot<SHM_TABLE_SLOTS; free_slot++)
-        if(hdr->free_tab_slots[free_slot])
-            break;
-    if(free_slot == SHM_TABLE_SLOTS)
-    {
-        shm_mutex_unlock(hdr);
-        return;
-    }
-    hdr->free_tab_slots[free_slot] = 0;
-    shm_mutex_unlock(hdr);
-    *buckets_tab      = get_shm_tab(hdr, free_slot);
-    *bucket_locks_tab = get_shm_lock_tab(hdr, free_slot);
-}
-
-static void free_entry(struct __hash *h, void *p)
-{
-    struct shm_hdr *hdr = get_shm_hdr(h);
-    uint32_t slot;
-
-    slot = ((uint32_t)((struct hash_entry *)p -
-                get_shm_entries(hdr)));
-    shm_add_to_freelist(hdr, slot);
-}
-
-static void free_buckets(struct __hash *h,
-                         struct bucket *buckets,
-                         struct bucket_lock *bucket_locks)
-{
-    struct shm_hdr *hdr = get_shm_hdr(h);
-    int slot;
-
-    if(!buckets || !bucket_locks)
-    {
-        assert(!buckets && !bucket_locks);
-        return;
-    }
-    slot = get_shm_slot(hdr, buckets);
-    assert(slot < SHM_TABLE_SLOTS);
-    assert((char *)bucket_locks == (char *)buckets + hdr->max_tab_size);
-    shm_mutex_lock(hdr);
-    assert(hdr->free_tab_slots[slot] == 0);
-    hdr->free_tab_slots[slot] = 1;
-    shm_mutex_unlock(hdr);
-}
-
-static int max_entries(struct __hash *h)
-{
-    struct shm_hdr *hdr = get_shm_hdr(h);
-
-    return hdr->nr_entries;
-}
-
-#endif /* !BIDIR_USE_STDMALLOC */
-
-
-/* The structures may be stored in shared memory region, with base address */
-/* stored in shm_base_addr. All the pointers in the above structures need  */
-/* to be relative to this base address (otherwise they would not make      */
-/* sense to other processes). Bellow accessor functions are used to        */
-/* convert between canonical (base address relative) and local addresses.  */
-/* C2L stands for CANONICAL_TO_LOCAL, and vice versa                       */
-#define C2L(_h, _p) ((typeof(_p))((unsigned long)(_p) +                        \
-            get_shm_baddr(_h)))
-#define L2C(_h, _p) ((typeof(_p))((unsigned long)(_p) -                        \
-            get_shm_baddr(_h)))
-
-
-#define HASH_LOCK_INIT(_h) ({                                                  \
-    int _ret;                                                                  \
-    pthread_rwlockattr_t _attr;                                                \
-                                                                               \
-    h->lock_alive = 1;                                                         \
-    _ret = pthread_rwlockattr_init(&_attr);                                    \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlockattr_setpshared(&_attr,                           \
-                                             PTHREAD_PROCESS_SHARED);          \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlock_init(&(_h)->hash_lock, &_attr);                  \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlockattr_destroy(&_attr);                             \
-                                                                               \
-    _ret;                                                                      \
-})
-
-#define HASH_LOCK_RDLOCK(_h) ({                                                \
-    int _ret;                                                                  \
-                                                                               \
-    if(!_h->lock_alive) _ret = ENOLCK;                                         \
-    else                                                                       \
-    {                                                                          \
-        struct timespec _ts;                                                   \
-        /* 10s timeout, long but ~matches disk spin-up times */                \
-        _ts.tv_sec = time(NULL) + 10;                                          \
-        _ts.tv_nsec = 0;                                                       \
-        _ret = pthread_rwlock_timedrdlock(&(_h)->hash_lock, &_ts);             \
-        if(_ret == ETIMEDOUT) _h->lock_alive = 0;                              \
-    }                                                                          \
-    _ret;                                                                      \
-})
-
-#define HASH_LOCK_RDUNLOCK(_h)                                                 \
-    pthread_rwlock_unlock(&(_h)->hash_lock)
-
-#define HASH_LOCK_WRLOCK(_h) ({                                                \
-    int _ret;                                                                  \
-                                                                               \
-    if(!_h->lock_alive) _ret = ENOLCK;                                         \
-    else                                                                       \
-    {                                                                          \
-        struct timespec _ts;                                                   \
-        _ts.tv_sec = time(NULL) + 10;                                          \
-        _ts.tv_nsec = 0UL;                                                     \
-        _ret = pthread_rwlock_timedwrlock(&(_h)->hash_lock, &_ts);             \
-        if(_ret == ETIMEDOUT) _h->lock_alive = 0;                              \
-    }                                                                          \
-    _ret;                                                                      \
-})
-
-#define HASH_LOCK_TRYWRLOCK(_h) ({                                             \
-    int _ret = (_h->lock_alive ?                                               \
-                    pthread_rwlock_trywrlock(&(_h)->hash_lock) :               \
-                    ENOLCK);                                                   \
-    _ret;                                                                      \
-})
-
-#define HASH_LOCK_WRUNLOCK(_h)                                                 \
-    pthread_rwlock_unlock(&(_h)->hash_lock)
-
-
-#define BUCKET_LOCK_INIT(_h, _b) ({                                            \
-    int _ret;                                                                  \
-    pthread_rwlockattr_t _attr;                                                \
-                                                                               \
-    _ret = pthread_rwlockattr_init(&_attr);                                    \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlockattr_setpshared(&_attr,                           \
-                                             PTHREAD_PROCESS_SHARED);          \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlock_init(&(_b)->bucket_lock, &_attr);                \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlockattr_destroy(&_attr);                             \
-                                                                               \
-    _ret;                                                                      \
-})
-
-
-#define BUCKET_LOCK_RDLOCK(_h, _lock_tab, _idx) ({                             \
-    int _ret;                                                                  \
-    struct timespec _ts;                                                       \
-    struct bucket_lock *_lock = &(_lock_tab)[(_idx) / BUCKETS_PER_LOCK];       \
-                                                                               \
-    _ts.tv_sec = time(NULL) + 10;                                              \
-    _ts.tv_nsec = 0;                                                           \
-    _ret = pthread_rwlock_timedrdlock(&(_lock)->bucket_lock, &_ts);            \
-    if(_ret == ETIMEDOUT) (_h)->lock_alive = 0;                                \
-    _ret;                                                                      \
-})
-
-
-#define BUCKET_LOCK_RDUNLOCK(_h, _lock_tab, _idx) ({                           \
-    struct bucket_lock *_lock = &(_lock_tab)[(_idx) / BUCKETS_PER_LOCK];       \
-    pthread_rwlock_unlock(&(_lock)->bucket_lock);                              \
-})
-
-#define BUCKET_LOCK_WRLOCK(_h, _lock_tab, _idx) ({                             \
-    int _ret;                                                                  \
-    struct timespec _ts;                                                       \
-    struct bucket_lock *_lock = &(_lock_tab)[(_idx) / BUCKETS_PER_LOCK];       \
-                                                                               \
-    _ts.tv_sec = time(NULL) + 10;                                              \
-    _ts.tv_nsec = 0;                                                           \
-    _ret = pthread_rwlock_timedwrlock(&(_lock)->bucket_lock, &_ts);            \
-    if(_ret == ETIMEDOUT) (_h)->lock_alive = 0;                                \
-    _ret;                                                                      \
-})
-
-#define BUCKET_LOCK_WRUNLOCK(_h, _lock_tab, _idx) ({                           \
-    struct bucket_lock *_lock = &(_lock_tab)[(_idx) / BUCKETS_PER_LOCK];       \
-    pthread_rwlock_unlock(&(_lock)->bucket_lock);                              \
-})
-
-#define TWO_BUCKETS_LOCK_WRLOCK(_h, _blt1, _idx1, _blt2, _idx2)  ({            \
-    int _ret;                                                                  \
-    pthread_rwlock_t *_l1, *_l2;                                               \
-    struct timespec _ts;                                                       \
-    struct bucket_lock *_bl1 = &(_blt1)[(_idx1) / BUCKETS_PER_LOCK];           \
-    struct bucket_lock *_bl2 = &(_blt2)[(_idx2) / BUCKETS_PER_LOCK];           \
-                                                                               \
-    assert((_bl1) != (_bl2));                                                  \
-    if((_bl1) < (_bl2))                                                        \
-    {                                                                          \
-        _l1 = &(_bl1)->bucket_lock;                                            \
-        _l2 = &(_bl2)->bucket_lock;                                            \
-    }                                                                          \
-    else                                                                       \
-    {                                                                          \
-        _l1 = &(_bl2)->bucket_lock;                                            \
-        _l2 = &(_bl1)->bucket_lock;                                            \
-    }                                                                          \
-    _ts.tv_sec = time(NULL) + 10;                                              \
-    _ts.tv_nsec = 0;                                                           \
-    _ret = pthread_rwlock_timedwrlock(_l1, &_ts);                              \
-    _ts.tv_sec = time(NULL) + 10;                                              \
-    _ts.tv_nsec = 0;                                                           \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlock_timedwrlock(_l2, &_ts);                          \
-    if(_ret == ETIMEDOUT) (_h)->lock_alive = 0;                                \
-                                                                               \
-    _ret;                                                                      \
-})
-
-#define TWO_BUCKETS_LOCK_WRUNLOCK(_h, _blt1, _idx1, _blt2, _idx2) ({           \
-    int _ret;                                                                  \
-    struct bucket_lock *_bl1 = &(_blt1)[(_idx1) / BUCKETS_PER_LOCK];           \
-    struct bucket_lock *_bl2 = &(_blt2)[(_idx2) / BUCKETS_PER_LOCK];           \
-                                                                               \
-    _ret = pthread_rwlock_unlock(&(_bl1)->bucket_lock);                        \
-    if(_ret == 0)                                                              \
-        _ret = pthread_rwlock_unlock(&(_bl2)->bucket_lock);                    \
-                                                                               \
-    _ret;                                                                      \
-})
-
-
-
-
-static uint32_t hash_to_idx(struct __hash *h, uint32_t hash)
-{
-    return (hash % h->tab_size);
-}
-
-static void alloc_tab(struct __hash *h,
-                      int size,
-                      struct bucket **buckets_tab,
-                      struct bucket_lock **bucket_locks_tab)
-{
-    int i;
-
-    alloc_buckets(h, size, buckets_tab, bucket_locks_tab);
-    if(!(*buckets_tab) || !(*bucket_locks_tab))
-        goto error_out;
-    memset(*buckets_tab, 0, size * sizeof(struct bucket));
-    memset(*bucket_locks_tab, 0, nr_locks(size) * sizeof(struct bucket_lock));
-    for(i=0; i<nr_locks(size); i++)
-        if(BUCKET_LOCK_INIT(h, *bucket_locks_tab + i) != 0)
-            goto error_out;
-
-    return;
-error_out:
-    free_buckets(h, *buckets_tab, *bucket_locks_tab);
-    *buckets_tab = NULL;
-    *bucket_locks_tab = NULL;
-    return;
-}
-
-
-struct __hash *__hash_init(struct __hash *h, uint32_t min_size)
-{
-    uint32_t size;
-    uint16_t size_idx;
-    struct bucket *buckets;
-    struct bucket_lock *bucket_locks;
-
-    /* Sanity check on args */
-    if (min_size > hash_sizes[hash_sizes_len-1]) return NULL;
-    /* Find least size greater than init_size */
-    for(size_idx = 0; size_idx < hash_sizes_len; size_idx++)
-            if(hash_sizes[size_idx] >= min_size)
-                break;
-    size = hash_sizes[size_idx];
-
-    if(!h) return NULL;
-    alloc_tab(h, size, &buckets, &bucket_locks);
-    if(!buckets || !bucket_locks) goto alloc_fail;
-    h->key_tab         = L2C(h, buckets);
-    h->key_lock_tab    = L2C(h, bucket_locks);
-    alloc_tab(h, size, &buckets, &bucket_locks);
-    if(!buckets || !bucket_locks) goto alloc_fail;
-    h->value_tab       = L2C(h, buckets);
-    h->value_lock_tab  = L2C(h, bucket_locks);
-    /* Init all h variables */
-    if(HASH_LOCK_INIT(h) != 0) goto alloc_fail;
-    h->nr_ent = 0;
-    h->tab_size = size;
-    h->size_idx = size_idx;
-    h->max_load = (uint32_t)ceilf(hash_max_load_fact * size);
-    h->min_load = (uint32_t)ceilf(hash_min_load_fact * size);
-
-    return h;
-
-alloc_fail:
-    if(h->key_tab || h->key_lock_tab)
-        free_buckets(h, C2L(h, h->key_tab), C2L(h, h->key_lock_tab));
-    return NULL;
-}
-
-#undef __prim
-#undef __prim_t
-#undef __prim_tab
-#undef __prim_lock_tab
-#undef __prim_hash
-#undef __prim_cmp
-#undef __prim_next
-#undef __sec
-#undef __sec_t
-
-#define __prim             key
-#define __prim_t         __k_t
-#define __prim_tab         key_tab
-#define __prim_lock_tab    key_lock_tab
-#define __prim_hash      __key_hash
-#define __prim_cmp       __key_cmp
-#define __prim_next        key_next
-#define __sec              value
-#define __sec_t          __v_t
-int __key_lookup(struct __hash *h, __prim_t k, __sec_t *vp)
-{
-    struct hash_entry *entry;
-    struct bucket *b;
-    struct bucket_lock *blt;
-    uint32_t idx;
-
-    if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-    idx = hash_to_idx(h, __prim_hash(k));
-    b = C2L(h, &h->__prim_tab[idx]);
-    blt = C2L(h, h->__prim_lock_tab);
-    if(BUCKET_LOCK_RDLOCK(h, blt, idx) != 0) return -ENOLCK;
-    entry = b->hash_entry;
-    while(entry != NULL)
-    {
-        entry = C2L(h, entry);
-        if(__prim_cmp(k, entry->__prim))
-        {
-            /* Unlock here */
-            *vp = entry->__sec;
-            BUCKET_LOCK_RDUNLOCK(h, blt, idx);
-            HASH_LOCK_RDUNLOCK(h);
-            return 1;
-        }
-        entry = entry->__prim_next;
-    }
-    BUCKET_LOCK_RDUNLOCK(h, blt, idx);
-    HASH_LOCK_RDUNLOCK(h);
-    return 0;
-}
-
-/* value lookup is an almost exact copy of key lookup */
-#undef __prim
-#undef __prim_t
-#undef __prim_tab
-#undef __prim_lock_tab
-#undef __prim_hash
-#undef __prim_cmp
-#undef __prim_next
-#undef __sec
-#undef __sec_t
-
-#define __prim             value
-#define __prim_t         __v_t
-#define __prim_tab         value_tab
-#define __prim_lock_tab    value_lock_tab
-#define __prim_hash      __value_hash
-#define __prim_cmp       __value_cmp
-#define __prim_next        value_next
-#define __sec              key
-#define __sec_t          __k_t
-int __value_lookup(struct __hash *h, __prim_t k, __sec_t *vp)
-{
-    struct hash_entry *entry;
-    struct bucket *b;
-    struct bucket_lock *blt;
-    uint32_t idx;
-
-    if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-    idx = hash_to_idx(h, __prim_hash(k));
-    b = C2L(h, &h->__prim_tab[idx]);
-    blt = C2L(h, h->__prim_lock_tab);
-    if(BUCKET_LOCK_RDLOCK(h, blt, idx) != 0) return -ENOLCK;
-    entry = b->hash_entry;
-    while(entry != NULL)
-    {
-        entry = C2L(h, entry);
-        if(__prim_cmp(k, entry->__prim))
-        {
-            /* Unlock here */
-            *vp = entry->__sec;
-            BUCKET_LOCK_RDUNLOCK(h, blt, idx);
-            HASH_LOCK_RDUNLOCK(h);
-            return 1;
-        }
-        entry = entry->__prim_next;
-    }
-    BUCKET_LOCK_RDUNLOCK(h, blt, idx);
-    HASH_LOCK_RDUNLOCK(h);
-    return 0;
-}
-
-int __insert(struct __hash *h, __k_t k, __v_t v)
-{
-    uint32_t k_idx, v_idx;
-    struct hash_entry *entry;
-    struct bucket *bk, *bv;
-    struct bucket_lock *bltk, *bltv;
-
-    /* Allocate new entry before any locks (in case it fails) */
-    entry = (struct hash_entry*)
-                    alloc_entry(h, sizeof(struct hash_entry));
-    if(!entry) return 0;
-
-    if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-    /* Read from nr_ent is atomic(TODO check), no need for fancy accessors */
-    if(h->nr_ent+1 > h->max_load)
-    {
-        /* Resize needs the write lock, drop read lock temporarily */
-        HASH_LOCK_RDUNLOCK(h);
-        hash_resize(h);
-        if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-    }
-
-    /* Init the entry */
-    entry->key = k;
-    entry->value = v;
-
-    /* Work out the indicies */
-    k_idx = hash_to_idx(h, __key_hash(k));
-    v_idx = hash_to_idx(h, __value_hash(v));
-
-    /* Insert */
-    bk   = C2L(h, &h->key_tab[k_idx]);
-    bv   = C2L(h, &h->value_tab[v_idx]);
-    bltk = C2L(h, h->key_lock_tab);
-    bltv = C2L(h, h->value_lock_tab);
-    if(TWO_BUCKETS_LOCK_WRLOCK(h, bltk, k_idx, bltv, v_idx) != 0)
-        return -ENOLCK;
-    entry->key_next = bk->hash_entry;
-    bk->hash_entry = L2C(h, entry);
-    entry->value_next = bv->hash_entry;
-    bv->hash_entry = L2C(h, entry);
-    TWO_BUCKETS_LOCK_WRUNLOCK(h, bltk, k_idx, bltv, v_idx);
-
-    /* Book keeping */
-    atomic_inc(&h->nr_ent);
-
-    HASH_LOCK_RDUNLOCK(h);
-
-    return 1;
-}
-
-
-#undef __prim
-#undef __prim_t
-#undef __prim_tab
-#undef __prim_lock_tab
-#undef __prim_hash
-#undef __prim_cmp
-#undef __prim_next
-#undef __sec
-#undef __sec_t
-#undef __sec_tab
-#undef __sec_lock_tab
-#undef __sec_hash
-#undef __sec_next
-
-#define __prim             key
-#define __prim_t         __k_t
-#define __prim_tab         key_tab
-#define __prim_lock_tab    key_lock_tab
-#define __prim_hash      __key_hash
-#define __prim_cmp       __key_cmp
-#define __prim_next        key_next
-#define __sec              value
-#define __sec_t          __v_t
-#define __sec_tab          value_tab
-#define __sec_lock_tab     value_lock_tab
-#define __sec_hash       __value_hash
-#define __sec_next         value_next
-
-int __key_remove(struct __hash *h, __prim_t k, __sec_t *vp)
-{
-    struct hash_entry *e, *es, **pek, **pev;
-    struct bucket *bk, *bv;
-    struct bucket_lock *bltk, *bltv;
-    uint32_t old_kidx, kidx, vidx, min_load, nr_ent;
-    __prim_t ks;
-    __sec_t vs;
-
-    if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-
-again:
-    old_kidx = kidx = hash_to_idx(h, __prim_hash(k));
-    bk = C2L(h, &h->__prim_tab[kidx]);
-    bltk = C2L(h, h->__prim_lock_tab);
-    if(BUCKET_LOCK_RDLOCK(h, bltk, kidx) != 0) return -ENOLCK;
-    pek = &(bk->hash_entry);
-    e = *pek;
-    while(e != NULL)
-    {
-        e = C2L(h, e);
-        if(__prim_cmp(k, e->__prim))
-        {
-            goto found;
-        }
-        pek = &(e->__prim_next);
-        e = *pek;
-    }
-
-    BUCKET_LOCK_RDUNLOCK(h, bltk, kidx);
-    HASH_LOCK_RDUNLOCK(h);
-
-    return 0;
-
-found:
-    /*
-     * Make local copy of key and value.
-     */
-    es = e;
-    ks = e->__prim;
-    vs = e->__sec;
-    kidx = hash_to_idx(h, __prim_hash(ks));
-    /* Being paranoid: check if kidx has not changed, so that we unlock the
-     * right bucket */
-    assert(old_kidx == kidx);
-    vidx = hash_to_idx(h, __sec_hash(vs));
-    bk   = C2L(h, &h->__prim_tab[kidx]);
-    bv   = C2L(h, &h->__sec_tab[vidx]);
-    bltk = C2L(h, h->__prim_lock_tab);
-    bltv = C2L(h, h->__sec_lock_tab);
-    BUCKET_LOCK_RDUNLOCK(h, bltk, kidx);
-    if(TWO_BUCKETS_LOCK_WRLOCK(h, bltk, kidx, bltv, vidx) != 0) return -ENOLCK;
-    pek = &(bk->hash_entry);
-    pev = &(bv->hash_entry);
-
-    /* Find the entry in both tables */
-    e = *pek;
-    while(e != NULL)
-    {
-        e = C2L(h, e);
-        if(e == es)
-        {
-            /* Being paranoid: make sure that the key and value are
-             * still the same. This is still not 100%, because, in
-             * principle, the entry could have got deleted, when we
-             * didn't hold the locks for a little while, and exactly
-             * the same entry reinserted. If the __k_t & __v_t are
-             * simple types than it probably doesn't matter, but if
-             * either is a pointer type, the actual structure might
-             * now be different. The chances that happens are very
-             * slim, but still, if that's a problem, the user needs to
-             * pay attention to the structure re-allocation */
-            if((memcmp(&(e->__prim), &ks, sizeof(__prim_t))) ||
-               (memcmp(&(e->__sec), &vs, sizeof(__sec_t))))
-                break;
-            goto found_again;
-        }
-        pek = &(e->__prim_next);
-        e = *pek;
-    }
-
-    TWO_BUCKETS_LOCK_WRUNLOCK(h, bltk, kidx, bltv, vidx);
-
-    /* Entry got removed in the meantime, try again */
-    goto again;
-
-found_again:
-    /* We are now comitted to the removal */
-    e = *pev;
-    while(e != NULL)
-    {
-        e = C2L(h, e);
-        if(e == es)
-        {
-            /* Both pek and pev are pointing to the right place, remove */
-            *pek = e->__prim_next;
-            *pev = e->__sec_next;
-
-            atomic_dec(&h->nr_ent);
-            nr_ent = h->nr_ent;
-            /* read min_load still under the hash lock! */
-            min_load = h->min_load;
-
-            TWO_BUCKETS_LOCK_WRUNLOCK(h, bltk, kidx, bltv, vidx);
-            HASH_LOCK_RDUNLOCK(h);
-
-            if(nr_ent < min_load)
-                hash_resize(h);
-            if(vp != NULL)
-                *vp = e->__sec;
-            free_entry(h, e);
-            return 1;
-        }
-        pev = &(e->__sec_next);
-        e = *pev;
-    }
-
-    /* We should never get here!, no need to unlock anything */
-    return -ENOLCK;
-}
-
-#undef __prim
-#undef __prim_t
-#undef __prim_tab
-#undef __prim_lock_tab
-#undef __prim_hash
-#undef __prim_cmp
-#undef __prim_next
-#undef __sec
-#undef __sec_t
-#undef __sec_tab
-#undef __sec_lock_tab
-#undef __sec_hash
-#undef __sec_next
-
-#define __prim             value
-#define __prim_t         __v_t
-#define __prim_tab         value_tab
-#define __prim_lock_tab    value_lock_tab
-#define __prim_hash      __value_hash
-#define __prim_cmp       __value_cmp
-#define __prim_next        value_next
-#define __sec              key
-#define __sec_t          __k_t
-#define __sec_tab          key_tab
-#define __sec_lock_tab     key_lock_tab
-#define __sec_hash       __key_hash
-#define __sec_next         key_next
-
-int __value_remove(struct __hash *h, __prim_t k, __sec_t *vp)
-{
-    struct hash_entry *e, *es, **pek, **pev;
-    struct bucket *bk, *bv;
-    struct bucket_lock *bltk, *bltv;
-    uint32_t old_kidx, kidx, vidx, min_load, nr_ent;
-    __prim_t ks;
-    __sec_t vs;
-
-    if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-
-again:
-    old_kidx = kidx = hash_to_idx(h, __prim_hash(k));
-    bk = C2L(h, &h->__prim_tab[kidx]);
-    bltk = C2L(h, h->__prim_lock_tab);
-    if(BUCKET_LOCK_RDLOCK(h, bltk, kidx) != 0) return -ENOLCK;
-    pek = &(bk->hash_entry);
-    e = *pek;
-    while(e != NULL)
-    {
-        e = C2L(h, e);
-        if(__prim_cmp(k, e->__prim))
-        {
-            goto found;
-        }
-        pek = &(e->__prim_next);
-        e = *pek;
-    }
-
-    BUCKET_LOCK_RDUNLOCK(h, bltk, kidx);
-    HASH_LOCK_RDUNLOCK(h);
-
-    return 0;
-
-found:
-    /*
-     * Make local copy of key and value.
-     */
-    es = e;
-    ks = e->__prim;
-    vs = e->__sec;
-    kidx = hash_to_idx(h, __prim_hash(ks));
-    /* Being paranoid: check if kidx has not changed, so that we unlock the
-     * right bucket */
-    assert(old_kidx == kidx);
-    vidx = hash_to_idx(h, __sec_hash(vs));
-    bk   = C2L(h, &h->__prim_tab[kidx]);
-    bv   = C2L(h, &h->__sec_tab[vidx]);
-    bltk = C2L(h, h->__prim_lock_tab);
-    bltv = C2L(h, h->__sec_lock_tab);
-    BUCKET_LOCK_RDUNLOCK(h, bltk, kidx);
-    if(TWO_BUCKETS_LOCK_WRLOCK(h, bltk, kidx, bltv, vidx) != 0) return -ENOLCK;
-    pek = &(bk->hash_entry);
-    pev = &(bv->hash_entry);
-
-    /* Find the entry in both tables */
-    e = *pek;
-    while(e != NULL)
-    {
-        e = C2L(h, e);
-        if(e == es)
-        {
-            /* Being paranoid: make sure that the key and value are
-             * still the same. This is still not 100%, because, in
-             * principle, the entry could have got deleted, when we
-             * didn't hold the locks for a little while, and exactly
-             * the same entry reinserted. If the __k_t & __v_t are
-             * simple types than it probably doesn't matter, but if
-             * either is a pointer type, the actual structure might
-             * now be different. The chances that happens are very
-             * slim, but still, if that's a problem, the user needs to
-             * pay attention to the structure re-allocation */
-            if((memcmp(&(e->__prim), &ks, sizeof(__prim_t))) ||
-               (memcmp(&(e->__sec), &vs, sizeof(__sec_t))))
-                break;
-            goto found_again;
-        }
-        pek = &(e->__prim_next);
-        e = *pek;
-    }
-
-    TWO_BUCKETS_LOCK_WRUNLOCK(h, bltk, kidx, bltv, vidx);
-
-    /* Entry got removed in the meantime, try again */
-    goto again;
-
-found_again:
-    /* We are now comitted to the removal */
-    e = *pev;
-    while(e != NULL)
-    {
-        e = C2L(h, e);
-        if(e == es)
-        {
-            /* Both pek and pev are pointing to the right place, remove */
-            *pek = e->__prim_next;
-            *pev = e->__sec_next;
-
-            atomic_dec(&h->nr_ent);
-            nr_ent = h->nr_ent;
-            /* read min_load still under the hash lock! */
-            min_load = h->min_load;
-
-            TWO_BUCKETS_LOCK_WRUNLOCK(h, bltk, kidx, bltv, vidx);
-            HASH_LOCK_RDUNLOCK(h);
-
-            if(nr_ent < min_load)
-                hash_resize(h);
-            if(vp != NULL)
-                *vp = e->__sec;
-            free_entry(h, e);
-            return 1;
-        }
-        pev = &(e->__sec_next);
-        e = *pev;
-    }
-
-    /* We should never get here!, no need to unlock anything */
-    return -ENOLCK;
-}
-
-
-int __hash_destroy(struct __hash *h,
-                   void (*entry_consumer)(__k_t k, __v_t v, void *p),
-                   void *d)
-{
-    struct hash_entry *e, *n;
-    struct bucket *b;
-    int i;
-
-    if(HASH_LOCK_WRLOCK(h) != 0) return -ENOLCK;
-
-    /* No need to lock individual buckets, with hash write lock  */
-    for(i=0; i < h->tab_size; i++)
-    {
-        b = C2L(h, &h->key_tab[i]);
-        e = b->hash_entry;
-        while(e != NULL)
-        {
-            e = C2L(h, e);
-            n = e->key_next;
-            if(entry_consumer)
-                entry_consumer(e->key, e->value, d);
-            free_entry(h, e);
-            e = n;
-        }
-    }
-    free_buckets(h, C2L(h, h->key_tab), C2L(h, h->key_lock_tab));
-    free_buckets(h, C2L(h, h->value_tab), C2L(h, h->value_lock_tab));
-
-    HASH_LOCK_WRUNLOCK(h);
-    h->lock_alive = 0;
-
-    return 0;
-}
-
-static void hash_resize(struct __hash *h)
-{
-    int new_size_idx, i, lock_ret;
-    uint32_t size, old_size, kidx, vidx;
-    struct bucket *t1, *t2, *b;
-    struct bucket_lock *l1, *l2;
-    struct hash_entry *e, *n;
-
-    /* We may fail to allocate the lock, if the resize is triggered while
-       we are iterating (under read lock) */
-    lock_ret = HASH_LOCK_TRYWRLOCK(h);
-    if(lock_ret != 0) return;
-
-    new_size_idx = h->size_idx;
-    /* Work out the new size */
-    if(h->nr_ent >= h->max_load)
-        new_size_idx = h->size_idx+1;
-    if(h->nr_ent < h->min_load)
-        new_size_idx = h->size_idx-1;
-    if((new_size_idx == h->size_idx) ||
-       (new_size_idx >= hash_sizes_len) ||
-       (new_size_idx < 0))
-    {
-        HASH_LOCK_WRUNLOCK(h);
-        return;
-    }
-
-    size = hash_sizes[new_size_idx];
-
-    /* Allocate the new sizes */
-    t1 = t2 = NULL;
-    l1 = l2 = NULL;
-    alloc_tab(h, size, &t1, &l1);
-    if(!t1 || !l1) goto alloc_fail;
-    alloc_tab(h, size, &t2, &l2);
-    if(!t2 || !l2) goto alloc_fail;
-
-    old_size = h->tab_size;
-    h->tab_size = size;
-    h->size_idx = new_size_idx;
-    h->max_load = (uint32_t)ceilf(hash_max_load_fact * size);
-    h->min_load = (uint32_t)ceilf(hash_min_load_fact * size);
-
-    /* Move the entries */
-    for(i=0; i < old_size; i++)
-    {
-        b = C2L(h, &h->key_tab[i]);
-        e = b->hash_entry;
-        while(e != NULL)
-        {
-            e = C2L(h, e);
-            n = e->key_next;
-            kidx =hash_to_idx(h, __key_hash(e->key));
-            vidx =hash_to_idx(h, __value_hash(e->value));
-            /* Move to the correct bucket */
-            e->key_next = t1[kidx].hash_entry;
-            t1[kidx].hash_entry = L2C(h, e);
-            e->value_next = t2[vidx].hash_entry;
-            t2[vidx].hash_entry = L2C(h, e);
-            e = n;
-        }
-    }
-    free_buckets(h, C2L(h, h->key_tab), C2L(h, h->key_lock_tab));
-    free_buckets(h, C2L(h, h->value_tab), C2L(h, h->value_lock_tab));
-    h->key_tab         = L2C(h, t1);
-    h->key_lock_tab    = L2C(h, l1);
-    h->value_tab       = L2C(h, t2);
-    h->value_lock_tab  = L2C(h, l2);
-
-    HASH_LOCK_WRUNLOCK(h);
-
-    return;
-
-alloc_fail:
-    /* If we failed to resize, adjust max/min load. This will stop us from
-     * retrying resize too frequently */ 
-    if(new_size_idx > h->size_idx)
-        h->max_load = (h->max_load + 2 * h->tab_size) / 2 + 1;
-    else 
-    if (new_size_idx < h->size_idx)
-        h->min_load = h->min_load / 2;
-    HASH_LOCK_WRUNLOCK(h);
-    if(t1 || l1) free_buckets(h, t1, l1);
-    if(t2 || l2) free_buckets(h, t2, l2);
-    return;
-}
-
-int __hash_iterator(struct __hash *h,
-                    int (*entry_consumer)(__k_t k, __v_t v, void *p),
-                    void *d)
-{
-    struct hash_entry *e, *n;
-    struct bucket *b;
-    struct bucket_lock *blt;
-    int i, brk_early;
-
-    if(HASH_LOCK_RDLOCK(h) != 0) return -ENOLCK;
-
-    for(i=0; i < h->tab_size; i++)
-    {
-        b = C2L(h, &h->key_tab[i]);
-        blt = C2L(h, h->key_lock_tab);
-        if(BUCKET_LOCK_RDLOCK(h, blt, i) != 0) return -ENOLCK;
-        e = b->hash_entry;
-        while(e != NULL)
-        {
-            e = C2L(h, e);
-            n = e->key_next;
-            brk_early = entry_consumer(e->key, e->value, d);
-            if(brk_early)
-            {
-                BUCKET_LOCK_RDUNLOCK(h, blt, i);
-                goto out;
-            }
-            e = n;
-        }
-        BUCKET_LOCK_RDUNLOCK(h, blt, i);
-    }
-out:
-    HASH_LOCK_RDUNLOCK(h);
-    return 0;
-}
-
-void __hash_sizes(struct __hash *h,
-                  uint32_t *nr_ent,
-                  uint32_t *max_nr_ent,
-                  uint32_t *tab_size,
-                  uint32_t *max_load,
-                  uint32_t *min_load)
-{
-    if(nr_ent     != NULL) *nr_ent     = h->nr_ent;
-    if(max_nr_ent != NULL) *max_nr_ent = max_entries(h); 
-    if(tab_size   != NULL) *tab_size   = h->tab_size;
-    if(max_load   != NULL) *max_load   = h->max_load;
-    if(min_load   != NULL) *min_load   = h->min_load;
-}
-
diff --git a/tools/memshr/bidir-hash.h b/tools/memshr/bidir-hash.h
deleted file mode 100644
index d32c8e4781..0000000000
--- a/tools/memshr/bidir-hash.h
+++ /dev/null
@@ -1,114 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __BIDIR_HASH_H__
-#define __BIDIR_HASH_H__
-
-#include <stdint.h>
-#include <string.h>
-#include "memshr-priv.h"
-
-typedef struct vbdblk {
-    uint64_t sec;
-    uint16_t disk_id;
-} vbdblk_t;
-
-
-#if defined FINGERPRINT_MAP || BLOCK_MAP 
-#define DEFINE_SINGLE_MAP 
-#endif
-
-/*******************************************************/
-/* Fingerprint map                                     */
-/*******************************************************/
-#if defined FINGERPRINT_MAP || !defined DEFINE_SINGLE_MAP
-
-#undef BIDIR_NAME_PREFIX
-#undef BIDIR_KEY
-#undef BIDIR_VALUE
-#undef BIDIR_KEY_T
-#undef BIDIR_VALUE_T
-static uint32_t fgprtshr_fgprt_hash(uint32_t h)
-{
-    return h;
-}
-
-static uint32_t fgprtshr_mfn_hash(uint64_t m)
-{
-    return (uint32_t)m;
-}
-
-static int fgprtshr_fgprt_cmp(uint32_t h1, uint32_t h2)
-{
-    return (h1 == h2);
-}
-
-static int fgprtshr_mfn_cmp(uint32_t m1, uint32_t m2)
-{
-    return (m1 == m2);
-}
-#define BIDIR_NAME_PREFIX       fgprtshr 
-#define BIDIR_KEY               fgprt 
-#define BIDIR_VALUE             mfn 
-#define BIDIR_KEY_T             uint32_t
-#define BIDIR_VALUE_T           xen_mfn_t
-#include "bidir-namedefs.h"
-
-#endif /* FINGERPRINT_MAP */
-
-
-/*******************************************************/
-/* Block<->Memory sharing handles                      */
-/*******************************************************/
-#if defined BLOCK_MAP || !defined DEFINE_SINGLE_MAP
-
-#undef BIDIR_NAME_PREFIX
-#undef BIDIR_KEY
-#undef BIDIR_VALUE
-#undef BIDIR_KEY_T
-#undef BIDIR_VALUE_T
-
-/* TODO better hashes! */
-static inline uint32_t blockshr_block_hash(vbdblk_t block)
-{
-    return (uint32_t)(block.sec) ^ (uint32_t)(block.disk_id);
-}
-
-static inline uint32_t blockshr_shrhnd_hash(share_tuple_t shrhnd)
-{
-    return ((uint32_t) shrhnd.handle);
-}
-
-static inline int blockshr_block_cmp(vbdblk_t b1, vbdblk_t b2)
-{
-    return (b1.sec == b2.sec) && (b1.disk_id == b2.disk_id);
-}
-
-static inline int blockshr_shrhnd_cmp(share_tuple_t h1, share_tuple_t h2)
-{
-    return ( !memcmp(&h1, &h2, sizeof(share_tuple_t)) );
-}
-#define BIDIR_NAME_PREFIX       blockshr
-#define BIDIR_KEY               block
-#define BIDIR_VALUE             shrhnd
-#define BIDIR_KEY_T             vbdblk_t
-#define BIDIR_VALUE_T           share_tuple_t
-#include "bidir-namedefs.h"
-
-#endif /* BLOCK_MAP */
-
-#endif /* __BIDIR_HASH_H__ */
diff --git a/tools/memshr/bidir-namedefs.h b/tools/memshr/bidir-namedefs.h
deleted file mode 100644
index 6ab4b3de8c..0000000000
--- a/tools/memshr/bidir-namedefs.h
+++ /dev/null
@@ -1,79 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#include "memshr-priv.h"
-
-/* Macros used to assemble the names */
-#define BIDIR_NAME_ONE_INTERNAL(prefix, name) \
-                                prefix ## _ ## name
-#define BIDIR_NAME_TWO_INTERNAL(prefix, name1, name2) \
-                                prefix ## _ ## name1 ## _ ## name2
-
-#define BIDIR_NAME_ONE(prefix, name) \
-                                BIDIR_NAME_ONE_INTERNAL(prefix, name)
-#define BIDIR_NAME_TWO(prefix, name1, name2) \
-                                BIDIR_NAME_TWO_INTERNAL(prefix, name1, name2)
-
-#define INTERNAL_NAME_ONE(name) BIDIR_NAME_ONE(BIDIR_NAME_PREFIX, name)
-#define INTERNAL_NAME_TWO(name1, name2) \
-                                BIDIR_NAME_TWO(BIDIR_NAME_PREFIX, name1, name2)
-
-/* Function/type names */
-#define __k_t                   BIDIR_KEY_T
-#define __v_t                   BIDIR_VALUE_T
-
-#define __hash                  INTERNAL_NAME_ONE(hash)
-#define __shm_hash_init         INTERNAL_NAME_ONE(shm_hash_init)
-#define __shm_hash_get          INTERNAL_NAME_ONE(shm_hash_get)
-#define __hash_init             INTERNAL_NAME_ONE(hash_init)
-#define __key_lookup            INTERNAL_NAME_TWO(BIDIR_KEY, lookup)
-#define __value_lookup          INTERNAL_NAME_TWO(BIDIR_VALUE, lookup)
-#define __insert                INTERNAL_NAME_ONE(insert)
-#define __key_remove            INTERNAL_NAME_TWO(BIDIR_KEY, remove)
-#define __value_remove          INTERNAL_NAME_TWO(BIDIR_VALUE, remove)
-#define __hash_destroy          INTERNAL_NAME_ONE(hash_destroy)
-#define __hash_iterator         INTERNAL_NAME_ONE(hash_iterator)
-
-#define __key_hash              INTERNAL_NAME_TWO(BIDIR_KEY, hash)
-#define __key_cmp               INTERNAL_NAME_TWO(BIDIR_KEY, cmp)
-#define __value_hash            INTERNAL_NAME_TWO(BIDIR_VALUE, hash)
-#define __value_cmp             INTERNAL_NAME_TWO(BIDIR_VALUE, cmp)
-
-#define __hash_sizes            INTERNAL_NAME_ONE(hash_sizes)
-
-
-/* Final function exports */
-struct __hash* __shm_hash_init(unsigned long shm_baddr, unsigned long shm_size);
-struct __hash* __shm_hash_get(unsigned long shm_baddr);
-struct __hash *__hash_init   (struct __hash *h, uint32_t min_size);
-int            __key_lookup  (struct __hash *h, __k_t k, __v_t *vp);
-int            __value_lookup(struct __hash *h, __v_t v, __k_t *kp);
-int            __insert      (struct __hash *h, __k_t k, __v_t v);
-int            __key_remove  (struct __hash *h, __k_t k, __v_t *vp);
-int            __value_remove(struct __hash *h, __v_t v, __k_t *kp);
-int            __hash_destroy(struct __hash *h,
-                    void (*entry_consumer)(__k_t k, __v_t v, void *p),
-                    void *d);
-int            __hash_iterator(struct __hash *h,
-                        int (*entry_consumer)(__k_t k, __v_t v, void *p),
-                        void *d);
-void           __hash_sizes(struct __hash *h,
-                            uint32_t *nr_ent,
-                            uint32_t *max_nr_ent,
-                            uint32_t *tab_size,
-                            uint32_t *max_load,
-                            uint32_t *min_load);
diff --git a/tools/memshr/interface.c b/tools/memshr/interface.c
deleted file mode 100644
index ba43c3de66..0000000000
--- a/tools/memshr/interface.c
+++ /dev/null
@@ -1,224 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#include <string.h>
-#include <inttypes.h>
-
-#include "memshr.h"
-#include "memshr-priv.h"
-#include "bidir-hash.h"
-#include "shm.h"
-#include "bidir-daemon.h"
-
-typedef struct {
-    int     enabled;
-    domid_t domid;
-    xc_interface *xc_handle;
-} memshr_vbd_info_t;
-
-memshr_vbd_info_t vbd_info = {0, DOMID_INVALID};
-
-
-typedef struct {
-    struct shared_memshr_info *shared_info;
-    struct fgprtshr_hash      *fgprts;
-    struct blockshr_hash      *blks;
-} private_memshr_info_t;
-
-private_memshr_info_t memshr;
-
-#define SHARED_INFO  (memshr.shared_info)
-
-void memshr_set_domid(int domid)
-{
-    vbd_info.domid = domid;
-}
-
-void memshr_daemon_initialize(void)
-{
-    void *shm_base_addr;
-    struct fgprtshr_hash *h;
-
-    memset(&memshr, 0, sizeof(private_memshr_info_t));
-
-    if((SHARED_INFO = shm_shared_info_open(1)) == NULL)
-    {
-        DPRINTF("Failed to init shared info.\n");
-        return;
-    }
-
-    if((memshr.fgprts = shm_fgprtshr_hash_open(1)) == NULL) 
-    {
-        DPRINTF("Failed to init fgprtshr hash.\n");
-        return;
-    }
-    memshr.shared_info->fgprtshr_hash_inited = 1;
-
-    if((memshr.blks = shm_blockshr_hash_open(1)) == NULL) 
-    {
-        DPRINTF("Failed to init blockshr hash.\n");
-        return;
-    }
-    memshr.shared_info->blockshr_hash_inited = 1;
-    
-    bidir_daemon_initialize(memshr.blks);
-}
-
-
-void memshr_vbd_initialize(void)
-{
-    xc_interface *xc_handle;
-
-    memset(&memshr, 0, sizeof(private_memshr_info_t));
-
-    if((SHARED_INFO = shm_shared_info_open(0)) == NULL)
-    {
-        DPRINTF("Failed to open shared info.\n");
-        return;
-    }
-
-    if(!SHARED_INFO->fgprtshr_hash_inited)
-    {
-        DPRINTF("fgprtshr hash not inited.\n");
-        return;
-    }
-
-    if((memshr.fgprts = shm_fgprtshr_hash_open(0)) == NULL)
-    {
-        DPRINTF("Failed to open fgprtshr_hash.\n");
-        return;
-    }
-
-    if((memshr.blks = shm_blockshr_hash_open(0)) == NULL)
-    {
-        DPRINTF("Failed to open blockshr_hash.\n");
-        return;
-    }
-
-    if(vbd_info.domid == DOMID_INVALID)
-        return;
-
-    if((xc_handle = xc_interface_open(0,0,0)) == 0)
-    {
-        DPRINTF("Failed to open XC interface.\n");
-        return;
-    }
-
-    vbd_info.xc_handle = xc_handle;
-    vbd_info.enabled = 1;
-}
-
-uint16_t memshr_vbd_image_get(const char* file)
-{
-    uint16_t id;
-
-    if(pthread_mutex_lock(&SHARED_INFO->lock)) goto error_out;
-    id = shm_vbd_image_get(file, SHARED_INFO->vbd_images);
-    if(pthread_mutex_unlock(&SHARED_INFO->lock)) goto error_out;
-
-    return id;
-error_out:
-    return 0;    
-}
-
-void memshr_vbd_image_put(uint16_t memshr_id)
-{
-    if(pthread_mutex_lock(&SHARED_INFO->lock)) return;
-    shm_vbd_image_put(memshr_id, SHARED_INFO->vbd_images);
-    if(pthread_mutex_unlock(&SHARED_INFO->lock)) return;
-}
-    
-int memshr_vbd_issue_ro_request(char *buf,
-                                grant_ref_t gref,
-                                uint16_t file_id,
-                                uint64_t sec, 
-                                int secs,
-                                share_tuple_t *hnd)
-{
-    vbdblk_t blk;
-    share_tuple_t source_st, client_st;
-    uint64_t c_hnd;
-    int ret;
-
-    *hnd = (share_tuple_t){ 0, 0, 0 };
-    if(!vbd_info.enabled) 
-        return -1;
-
-    if(secs != 8)
-        return -2;
-
-    /* Nominate the granted page for sharing */
-    ret = xc_memshr_nominate_gref(vbd_info.xc_handle,
-                                  vbd_info.domid,
-                                  gref,
-                                  &c_hnd);
-    /* If page couldn't be made sharable, we cannot do anything about it */
-    if(ret != 0)
-        return -3;
-
-    client_st = (share_tuple_t){ vbd_info.domid, gref, c_hnd };
-    *hnd = client_st;
-
-    /* Check if we've read matching disk block previously */
-    blk.sec     = sec;
-    blk.disk_id = file_id;
-    if(blockshr_block_lookup(memshr.blks, blk, &source_st) > 0)
-    {
-        ret = xc_memshr_share_grefs(vbd_info.xc_handle, source_st.domain, source_st.frame, 
-                                    source_st.handle, vbd_info.domid, gref, c_hnd);
-        if(!ret) return 0;
-        /* Handles failed to be shared => at least one of them must be invalid,
-           remove the relevant ones from the map */
-        switch(ret)
-        {
-            case XENMEM_SHARING_OP_S_HANDLE_INVALID:
-                ret = blockshr_shrhnd_remove(memshr.blks, source_st, NULL);
-                if(ret) DPRINTF("Could not rm invl s_hnd: %u %"PRId64" %"PRId64"\n", 
-                                    source_st.domain, source_st.frame, source_st.handle);
-                break;
-            case XENMEM_SHARING_OP_C_HANDLE_INVALID:
-                ret = blockshr_shrhnd_remove(memshr.blks, client_st, NULL);
-                if(ret) DPRINTF("Could not rm invl c_hnd: %u %"PRId64" %"PRId64"\n", 
-                                    client_st.domain, client_st.frame, client_st.handle);
-                break;
-            default:
-                break;
-        }
-        return -5;
-    }
-
-    return -4;
-}
-
-void memshr_vbd_complete_ro_request(share_tuple_t hnd,
-                                    uint16_t file_id, 
-                                    uint64_t sec, 
-                                    int secs)
-{
-    vbdblk_t blk;
-    
-    if(!vbd_info.enabled) 
-        return;
-
-    if(secs != 8)
-        return;
-
-    blk.sec     = sec;
-    blk.disk_id = file_id;
-    if(blockshr_insert(memshr.blks, blk, hnd) < 0)
-        DPRINTF("Could not insert block hint into hash.\n");
-}
diff --git a/tools/memshr/memshr-priv.h b/tools/memshr/memshr-priv.h
deleted file mode 100644
index f2c3f1f91d..0000000000
--- a/tools/memshr/memshr-priv.h
+++ /dev/null
@@ -1,33 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __MEMSHR_PRIV_H__
-#define __MEMSHR_PRIV_H__
-
-#include <syslog.h>
-#include <xenctrl.h>
-#include "memshr.h"
-
-#if 1
-#define DPRINTF(_f, _a...) syslog(LOG_INFO, _f, ##_a)
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-#define EPRINTF(_f, _a...) syslog(LOG_ERR, "memshr:%s: " _f, __func__, ##_a)
-
-#endif /* __MEMSHR_PRIV_H__ */
diff --git a/tools/memshr/memshr.h b/tools/memshr/memshr.h
deleted file mode 100644
index f3f898cd2c..0000000000
--- a/tools/memshr/memshr.h
+++ /dev/null
@@ -1,51 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __MEMSHR_H__
-#define __MEMSHR_H__
-
-#include <stdint.h>
-#include <xen/xen.h>
-#include <xen/grant_table.h>
-
-typedef uint64_t xen_mfn_t;
-
-typedef struct share_tuple 
-{
-    uint32_t domain;
-    uint64_t frame;
-    uint64_t handle;
-} share_tuple_t;
-
-extern void memshr_set_domid(int domid);
-extern void memshr_daemon_initialize(void);
-extern void memshr_vbd_initialize(void);
-extern uint16_t memshr_vbd_image_get(const char* file);
-extern void memshr_vbd_image_put(uint16_t memshr_id);
-extern int memshr_vbd_issue_ro_request(char *buf,
-                                       grant_ref_t gref,
-                                       uint16_t file_id, 
-                                       uint64_t sec, 
-                                       int secs,
-                                       share_tuple_t *hnd);
-extern void memshr_vbd_complete_ro_request(
-                                       share_tuple_t hnd,
-                                       uint16_t file_id, 
-                                       uint64_t sec, 
-                                       int secs);
-
-#endif /* __MEMSHR_H__ */
diff --git a/tools/memshr/shm.c b/tools/memshr/shm.c
deleted file mode 100644
index 00e9a51532..0000000000
--- a/tools/memshr/shm.c
+++ /dev/null
@@ -1,262 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "memshr-priv.h"
-#include "bidir-hash.h"
-#include "shm.h"
-
-#define MEMSHR_INFO_SHM_FILE  "/memshr-info"
-#define MEMSHR_INFO_MAGIC     0x15263748 
-
-#define FGPRT_HASH_SHM_FILE "/blktap-fgprts"
-#define FGPRT_HASH_PAGES    10000
-
-#define BLOCK_HASH_SHM_FILE "/blktap-blks"
-#define BLOCK_HASH_PAGES    10000
-
-typedef struct shm_area {
-    void*  base_addr;
-    size_t size;
-    int    fd;
-} shm_area_t;
-
-typedef struct {
-    struct shm_area shared_info_area;
-    struct shm_area fgprts_area;
-    struct shm_area blocks_area;
-} private_shm_info_t;
-
-private_shm_info_t shm_info;
-
-
-
-static int shm_area_open(const char *file, size_t size, int unlink, shm_area_t *shma)
-{ 
-    /* TODO: If blktapctrl can be restarted while system is running, this needs
-     * to be cleverer */
-    if(unlink) shm_unlink(file);
-
-    shma->size = size;
-    shma->fd = shm_open(file,
-                        (O_CREAT | O_RDWR),
-                        (S_IREAD | S_IWRITE));
-
-    if(shma->fd < 0) return -1;
-
-    if(ftruncate(shma->fd, size) < 0) return -2;
-
-    shma->base_addr = mmap(NULL, 
-                      size,
-                      PROT_READ | PROT_WRITE, 
-                      MAP_SHARED,
-                      shma->fd,
-                      0);
-    
-    if(shma->base_addr == MAP_FAILED) return -2;
-
-    return 0;
-}
-
-static void shm_area_close(shm_area_t *shma)
-{
-    munmap(shma->base_addr, shma->size);
-    close(shma->fd);
-}
-
-
-shared_memshr_info_t * shm_shared_info_open(int unlink)
-{
-    shared_memshr_info_t *shared_info;
-    pthread_mutexattr_t  lock_attr;
-    int nr_pages, i;
-
-    nr_pages = (sizeof(shared_memshr_info_t) >> XC_PAGE_SHIFT) + 1;
-    if(shm_area_open(MEMSHR_INFO_SHM_FILE, 
-                     nr_pages * XC_PAGE_SIZE,
-                     unlink, 
-                     &(shm_info.shared_info_area)) < 0)
-    {
-        DPRINTF("Failed to open shma for shared info.\n");
-        return NULL;
-    }
-    shared_info = (shared_memshr_info_t *)
-                             shm_info.shared_info_area.base_addr;
-    if(unlink)
-    {
-        memset(shared_info, 0, sizeof(shared_memshr_info_t));
-        if(pthread_mutexattr_init(&lock_attr) ||
-           pthread_mutexattr_setpshared(&lock_attr, PTHREAD_PROCESS_SHARED) ||
-           pthread_mutex_init(&shared_info->lock, &lock_attr) ||
-           pthread_mutexattr_destroy(&lock_attr))
-        {
-            DPRINTF("Failed to init shared info lock.\n");
-            return NULL;
-        }
-        strcpy(shared_info->vbd_images[0].file, "list-head");
-        for(i=1; i<MAX_NR_VBD_IMAGES; i++)
-        {
-            shared_info->vbd_images[i].next = i; 
-            shared_info->vbd_images[i].prev = i; 
-        }
-        shared_info->magic = MEMSHR_INFO_MAGIC;
-    } 
-    else
-    if(shared_info->magic != MEMSHR_INFO_MAGIC)
-    {
-        DPRINTF("Incorrect magic in shared info.\n");
-        return NULL;
-    }
-    
-    return shared_info;
-}
-
-
-struct fgprtshr_hash * shm_fgprtshr_hash_open(int unlink)
-{
-    struct fgprtshr_hash *h;
-    if(shm_area_open(FGPRT_HASH_SHM_FILE, 
-                     FGPRT_HASH_PAGES * XC_PAGE_SIZE,
-                     unlink, 
-                     &(shm_info.fgprts_area)) < 0)
-    {
-        DPRINTF("Failed to init shma for fgprtshr_hash.\n");
-        return NULL;
-    }
-
-    if(unlink)
-    {
-        h = fgprtshr_shm_hash_init(
-                     (unsigned long) shm_info.fgprts_area.base_addr, 
-                     FGPRT_HASH_PAGES * XC_PAGE_SIZE);
-    } else
-    {
-        h = fgprtshr_shm_hash_get(
-                     (unsigned long) shm_info.fgprts_area.base_addr); 
-    }
-        
-    return h;
-} 
-
-struct blockshr_hash * shm_blockshr_hash_open(int unlink)
-{
-    struct blockshr_hash *h;
-    if(shm_area_open(BLOCK_HASH_SHM_FILE, 
-                     BLOCK_HASH_PAGES * XC_PAGE_SIZE,
-                     unlink, 
-                     &(shm_info.blocks_area)) < 0)
-    {
-        DPRINTF("Failed to init shma for blockshr_hash.\n");
-        return NULL;
-    }
-
-    if(unlink)
-    {
-        h = blockshr_shm_hash_init(
-                     (unsigned long) shm_info.blocks_area.base_addr, 
-                     BLOCK_HASH_PAGES * XC_PAGE_SIZE);
-    } else
-    {
-        h = blockshr_shm_hash_get(
-                     (unsigned long) shm_info.blocks_area.base_addr); 
-    }
-        
-    return h;
-} 
-
-uint16_t shm_vbd_image_get(const char* file, vbd_image_info_t *vbd_imgs)
-{
-    vbd_image_info_t *img, *next_img;
-    int i, img_id;
-
-    /* Try to find the file in the existing list first */ 
-    img = vbd_imgs;
-    while(img->next != 0)
-    {
-        img = vbd_imgs + img->next;
-        if(strncmp(img->file, file, MAX_NAME_LEN) == 0)
-        {
-            img->ref_cnt++;
-            return (uint16_t)(img - vbd_imgs); 
-        }
-    }
-    
-    /* Couldn't find an existing entry. We need to add one. Find empty slot */ 
-    for(i=1; i<MAX_NR_VBD_IMAGES; i++)
-    {
-        img = vbd_imgs + i;
-        if((img->next == i) && (img->prev == i))
-            break;
-    }
-    /* No entries left! */
-    if(i == MAX_NR_VBD_IMAGES)
-    {
-        DPRINTF("No space in vbds table.\n");
-        return 0;
-    }
-    if(strlen(file) > MAX_NAME_LEN - 1)
-    {
-        DPRINTF("Filename: %s too long (>%d).\n", file, MAX_NAME_LEN - 1);
-        return 0; 
-    }
-    /* Init the entry */
-    img_id = (img - vbd_imgs);
-    next_img = vbd_imgs + vbd_imgs[0].next;
-    strcpy(img->file, file);
-    img->ref_cnt = 1;
-    img->next = vbd_imgs[0].next;
-    img->prev = 0;
-    next_img->prev = img_id;
-    vbd_imgs[0].next = img_id;
-
-    return img_id;
-}
-
-
-void shm_vbd_image_put(uint16_t memshr_id, vbd_image_info_t *vbd_imgs)
-{
-    vbd_image_info_t *img, *next_img, *prev_img;
-    
-    img = vbd_imgs + memshr_id;
-    if(img->ref_cnt == 0)
-    {
-        DPRINTF("Incorrect image put.\n");
-        return;
-    }
-
-    img->ref_cnt--; 
-
-    /* Remove from list if ref_cnt is zero */
-    if(img->ref_cnt == 0)
-    {
-        next_img = vbd_imgs + img->next;
-        prev_img = vbd_imgs + img->prev;
-        prev_img->next = img->next;
-        next_img->prev = img->prev;
-        img->next = img->prev = (img - vbd_imgs);
-        memset(img->file, 0, MAX_NAME_LEN);
-    }
-}
-
diff --git a/tools/memshr/shm.h b/tools/memshr/shm.h
deleted file mode 100644
index adb6eb9754..0000000000
--- a/tools/memshr/shm.h
+++ /dev/null
@@ -1,49 +0,0 @@ 
-/******************************************************************************
- *
- * Copyright (c) 2009 Citrix Systems, Inc. (Grzegorz Milos)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __SHM_H__
-#define __SHM_H__
-
-#include <pthread.h>
-#include <unistd.h>
-
-#define MAX_NAME_LEN  1000
-
-typedef struct vbd_image_info {
-    char     file[MAX_NAME_LEN];
-    int      ref_cnt;
-    uint16_t next;
-    uint16_t prev;
-} vbd_image_info_t;
-
-#define MAX_NR_VBD_IMAGES   4096
- 
-typedef struct shared_memshr_info {
-    unsigned long    magic;
-    pthread_mutex_t  lock;
-    int              fgprtshr_hash_inited;
-    int              blockshr_hash_inited;
-    vbd_image_info_t vbd_images[MAX_NR_VBD_IMAGES];
-} shared_memshr_info_t;
-
-shared_memshr_info_t * shm_shared_info_open(int unlink);
-struct fgprtshr_hash * shm_fgprtshr_hash_open(int unlink);
-struct blockshr_hash * shm_blockshr_hash_open(int unlink);
-uint16_t shm_vbd_image_get(const char* file, vbd_image_info_t *vbd_imgs);
-void     shm_vbd_image_put(uint16_t memshr_id, vbd_image_info_t *vbd_imgs);
-
-#endif /* __SHM_H__ */