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__ */
